From 37763ba99cef2e04c80beb76aa65772edb1bfd01 Mon Sep 17 00:00:00 2001 From: Simon Esposito Date: Mon, 1 Feb 2021 14:51:59 +0000 Subject: [PATCH] Fix js runtime concurrency issue. (#542) Reference functions by their global object key instead of calling .Extract() on the goja value, which would keep a reference to runtime used for function registration, causing concurrency issues under concurrent loads. Lookup the function indentifiers in the js code AST during registration. This disallows registring inlined (anonymous) functions, or invoking the initializer outside the scope of the InitModule function. --- go.sum | 18 - server/runtime_javascript.go | 66 +-- server/runtime_javascript_init.go | 610 +++++++++++++++++------- server/runtime_javascript_match_core.go | 17 +- 4 files changed, 490 insertions(+), 221 deletions(-) diff --git a/go.sum b/go.sum index 6f00a0aee..64eba8a4b 100644 --- a/go.sum +++ b/go.sum @@ -109,7 +109,6 @@ github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2 h1:Ujru1hufTHVb++eG6OuNDKMxZnGIvF6o/u8q/8h2+I4= github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= github.com/glycerine/go-unsnap-stream v0.0.0-20190901134440-81cf024a9e0a h1:FQqoVvjbiUioBBFUL5up+h+GdCa/AnJsL/1bIs/veSI= github.com/glycerine/go-unsnap-stream v0.0.0-20190901134440-81cf024a9e0a/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= @@ -145,14 +144,10 @@ github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= @@ -160,7 +155,6 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= @@ -171,7 +165,6 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -250,7 +243,6 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0j github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae h1:VeRdUYdCw49yizlSbMEn2SZ+gT+3IUKx8BqxyQdz+BY= github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM= github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw= @@ -358,7 +350,6 @@ golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTk golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= @@ -392,7 +383,6 @@ golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= @@ -441,23 +431,19 @@ golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642 h1:B6caxRw+hozq68X2MY7jEpZh/cr4/aHLv9xU8Kkadrw= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200926100807-9d91bd62050c h1:38q6VNPWR010vN82/SB121GujZNIfAUb4YttE2rhGuc= golang.org/x/sys v0.0.0-20200926100807-9d91bd62050c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -481,7 +467,6 @@ golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 h1:hKsoRgsbwY1NafxrwTs+k64bikrLBkAgPir1TNCj3Zs= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -575,7 +560,6 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= @@ -591,7 +575,6 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= @@ -618,7 +601,6 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4 h1:UoveltGrhghAA7ePc+e+QYDHXrBps2PqFZiHkGR/xK8= diff --git a/server/runtime_javascript.go b/server/runtime_javascript.go index d9088abf8..5edeaeae9 100644 --- a/server/runtime_javascript.go +++ b/server/runtime_javascript.go @@ -21,6 +21,7 @@ import ( "errors" "fmt" "github.com/dop251/goja" + "github.com/dop251/goja/ast" "github.com/gofrs/uuid" "github.com/golang/protobuf/jsonpb" "github.com/golang/protobuf/proto" @@ -118,6 +119,7 @@ type RuntimeJSModule struct { Name string Path string Program *goja.Program + Ast *ast.Program } type RuntimeJSModuleCache struct { @@ -166,7 +168,7 @@ func (rp *RuntimeProviderJS) Rpc(ctx context.Context, id string, queryParams map rp.Put(r) return "", ErrRuntimeRPCNotFound, codes.NotFound } - fn, _ := goja.AssertFunction(r.vm.ToValue(jsFn)) + fn, _ := goja.AssertFunction(r.vm.ToValue(r.vm.Get(jsFn.(string)))) retValue, err, code := r.InvokeFunction(RuntimeExecutionModeRPC, id, fn, queryParams, userID, username, vars, expiry, sessionID, clientIP, clientPort, payload) rp.Put(r) if err != nil { @@ -211,7 +213,7 @@ func (rp *RuntimeProviderJS) BeforeRt(ctx context.Context, id string, logger *za return nil, errors.New("Could not run runtime Before function.") } - fn, _ := goja.AssertFunction(r.vm.ToValue(jsFn)) + fn, _ := goja.AssertFunction(r.vm.ToValue(r.vm.Get(jsFn.(string)))) result, fnErr, _ := r.InvokeFunction(RuntimeExecutionModeBefore, id, fn, nil, userID, username, vars, expiry, sessionID, clientIP, clientPort, envelopeMap) rp.Put(r) @@ -262,7 +264,7 @@ func (rp *RuntimeProviderJS) AfterRt(ctx context.Context, id string, logger *zap return errors.New("Could not run runtime After function.") } - fn, _ := goja.AssertFunction(r.vm.ToValue(jsFn)) + fn, _ := goja.AssertFunction(r.vm.ToValue(r.vm.Get(jsFn.(string)))) _, fnErr, _ := r.InvokeFunction(RuntimeExecutionModeAfter, id, fn, nil, userID, username, vars, expiry, sessionID, clientIP, clientPort, envelopeMap) rp.Put(r) @@ -309,7 +311,7 @@ func (rp *RuntimeProviderJS) BeforeReq(ctx context.Context, id string, logger *z } } - fn, _ := goja.AssertFunction(r.vm.ToValue(jsFn)) + fn, _ := goja.AssertFunction(r.vm.ToValue(r.vm.Get(jsFn.(string)))) result, fnErr, code := r.InvokeFunction(RuntimeExecutionModeBefore, id, fn, nil, userID, username, vars, expiry, "", clientIP, clientPort, reqMap) rp.Put(r) @@ -394,7 +396,7 @@ func (rp *RuntimeProviderJS) AfterReq(ctx context.Context, id string, logger *za } } - fn, _ := goja.AssertFunction(r.vm.ToValue(jsFn)) + fn, _ := goja.AssertFunction(r.vm.ToValue(r.vm.Get(jsFn.(string)))) _, fnErr, _ := r.InvokeFunction(RuntimeExecutionModeAfter, id, fn, nil, userID, username, vars, expiry, "", clientIP, clientPort, resMap, reqMap) rp.Put(r) @@ -1388,12 +1390,14 @@ func NewRuntimeProviderJS(logger, startupLogger *zap.Logger, db *sql.DB, jsonpbM return nil, nil } - return NewRuntimeJavascriptMatchCore(logger, name, db, jsonpbMarshaler, jsonpbUnmarshaler, config, socialClient, leaderboardCache, leaderboardRankCache, localCache, leaderboardScheduler, sessionRegistry, matchRegistry, tracker, streamManager, router, matchProvider.CreateMatch, eventFn, id, node, stopped, mc) + return NewRuntimeJavascriptMatchCore(logger, name, db, jsonpbMarshaler, jsonpbUnmarshaler, config, socialClient, leaderboardCache, leaderboardRankCache, localCache, leaderboardScheduler, sessionRegistry, matchRegistry, tracker, streamManager, router, matchProvider.CreateMatch, eventFn, id, node, stopped, mc, modCache) }) runtimeProviderJS.newFn = func() *RuntimeJS { runtime := goja.New() + runtime.RunProgram(modCache.Modules[modCache.Names[0]].Program) + jsLogger := NewJsLogger(logger) jsLoggerValue := runtime.ToValue(jsLogger.Constructor(runtime)) jsLoggerInst, err := runtime.New(jsLoggerValue) @@ -1476,6 +1480,7 @@ func cacheJavascriptModules(logger *zap.Logger, path, entrypoint string) (*Runti } modName := filepath.Base(entrypoint) + ast, _ := goja.Parse(modName, string(content)) prg, err := goja.Compile(modName, string(content), true) if err != nil { logger.Error("Could not compile JavaScript module", zap.String("module", modName), zap.Error(err)) @@ -1486,6 +1491,7 @@ func cacheJavascriptModules(logger *zap.Logger, path, entrypoint string) (*Runti Name: modName, Path: absEntrypoint, Program: prg, + Ast: ast, }) return moduleCache, nil @@ -1708,7 +1714,9 @@ func evalRuntimeModules(rp *RuntimeProviderJS, modCache *RuntimeJSModuleCache, m r := goja.New() - initializer := NewRuntimeJavascriptInitModule(logger, announceCallbackFn) + // TODO: refactor and simplify modCache + modName := modCache.Names[0] + initializer := NewRuntimeJavascriptInitModule(logger, modCache.Modules[modName].Ast, announceCallbackFn) initializerValue := r.ToValue(initializer.Constructor(r)) initializerInst, err := r.New(initializerValue) if err != nil { @@ -1729,33 +1737,31 @@ func evalRuntimeModules(rp *RuntimeProviderJS, modCache *RuntimeJSModuleCache, m return nil, nil, err } - for _, modName := range modCache.Names { - _, err = r.RunProgram(modCache.Modules[modName].Program) - if err != nil { - return nil, nil, err - } + _, err = r.RunProgram(modCache.Modules[modName].Program) + if err != nil { + return nil, nil, err + } - initMod := r.Get("InitModule") - initModFn, ok := goja.AssertFunction(initMod) - if !ok { - logger.Error("InitModule function not found. Function must be defined at top level.", zap.String("module", modName)) - return nil, nil, errors.New(INIT_MODULE_FN_NAME + " function not found.") - } + initMod := r.Get("InitModule") + initModFn, ok := goja.AssertFunction(initMod) + if !ok { + logger.Error("InitModule function not found. Function must be defined at top level.", zap.String("module", modName)) + return nil, nil, errors.New(INIT_MODULE_FN_NAME + " function not found.") + } - if dryRun { - // Parse JavaScript code for syntax errors but do not execute the InitModule function. - return nil, nil, nil - } + if dryRun { + // Parse JavaScript code for syntax errors but do not execute the InitModule function. + return nil, nil, nil + } - // Execute init module function - ctx := NewRuntimeJsInitContext(r, rp.config.GetName(), rp.config.GetRuntime().Environment) - _, err = initModFn(goja.Null(), ctx, jsLoggerInst, nkInst, initializerInst) - if err != nil { - if exErr, ok := err.(*goja.Exception); ok { - return nil, nil, errors.New(exErr.String()) - } - return nil, nil, err + // Execute init module function + ctx := NewRuntimeJsInitContext(r, rp.config.GetName(), rp.config.GetRuntime().Environment) + _, err = initModFn(goja.Null(), ctx, jsLoggerInst, nkInst, initializerInst) + if err != nil { + if exErr, ok := err.(*goja.Exception); ok { + return nil, nil, errors.New(exErr.String()) } + return nil, nil, err } return initializer.Callbacks, initializer.MatchCallbacks, nil diff --git a/server/runtime_javascript_init.go b/server/runtime_javascript_init.go index e4141f60a..b450ab70b 100644 --- a/server/runtime_javascript_init.go +++ b/server/runtime_javascript_init.go @@ -15,15 +15,21 @@ package server import ( + "errors" + "fmt" "strings" "sync" + "github.com/dop251/goja/ast" + "github.com/dop251/goja" "go.uber.org/zap" ) const INIT_MODULE_FN_NAME = "InitModule" +var inlinedFunctionError = errors.New("function literal found: javascript functions cannot be inlined") + type RuntimeJavascriptMatchHandlers struct { lock *sync.RWMutex mapping map[string]*jsMatchHandlers @@ -68,9 +74,10 @@ type RuntimeJavascriptInitModule struct { Callbacks *RuntimeJavascriptCallbacks MatchCallbacks *RuntimeJavascriptMatchHandlers announceCallbackFn func(RuntimeExecutionMode, string) + ast *ast.Program } -func NewRuntimeJavascriptInitModule(logger *zap.Logger, announceCallbackFn func(RuntimeExecutionMode, string)) *RuntimeJavascriptInitModule { +func NewRuntimeJavascriptInitModule(logger *zap.Logger, ast *ast.Program, announceCallbackFn func(RuntimeExecutionMode, string)) *RuntimeJavascriptInitModule { callbacks := &RuntimeJavascriptCallbacks{ Rpc: make(map[string]interface{}), Before: make(map[string]interface{}), @@ -87,6 +94,7 @@ func NewRuntimeJavascriptInitModule(logger *zap.Logger, announceCallbackFn func( announceCallbackFn: announceCallbackFn, Callbacks: callbacks, MatchCallbacks: matchCallbacks, + ast: ast, } } @@ -265,543 +273,599 @@ func (im *RuntimeJavascriptInitModule) registerRpc(r *goja.Runtime) func(goja.Fu panic(r.NewTypeError("expects a function")) } + fnKey, err := im.extractRpcFn(r, key) + if err != nil { + panic(r.NewGoError(err)) + } + lKey := strings.ToLower(key) - im.registerCallbackFn(RuntimeExecutionModeRPC, lKey, fn.Export()) + im.registerCallbackFn(RuntimeExecutionModeRPC, lKey, fnKey) im.announceCallbackFn(RuntimeExecutionModeRPC, lKey) return goja.Undefined() } } +func (im *RuntimeJavascriptInitModule) extractRpcFn(r *goja.Runtime, fnName string) (string, error) { + for _, dec := range im.ast.DeclarationList { + var fl *ast.FunctionLiteral + if varDec, ok := dec.(*ast.VariableDeclaration); ok { + fl, ok = varDec.List[0].Initializer.(*ast.FunctionLiteral) + if !ok || varDec.List[0].Name != INIT_MODULE_FN_NAME { + continue + } + } else if fd, ok := dec.(*ast.FunctionDeclaration); ok { + fl = fd.Function + if fl.Name.Name != INIT_MODULE_FN_NAME { + continue + } + } + + callerName := fl.ParameterList.List[3].Name + if l, ok := fl.Body.(*ast.BlockStatement); ok { + for _, exp := range l.List { + if expStat, ok := exp.(*ast.ExpressionStatement); ok { + if callExp, ok := expStat.Expression.(*ast.CallExpression); ok { + if callee, ok := callExp.Callee.(*ast.DotExpression); ok { + if callee.Left.(*ast.Identifier).Name == callerName && callee.Identifier.Name == "registerRpc" { + if modNameArg, ok := callExp.ArgumentList[0].(*ast.Identifier); ok { + id := modNameArg.Name.String() + if r.Get(id).String() != fnName { + continue + } + } else if modNameArg, ok := callExp.ArgumentList[0].(*ast.StringLiteral); ok { + if modNameArg.Value.String() != fnName { + continue + } + } + + if modNameArg, ok := callExp.ArgumentList[1].(*ast.Identifier); ok { + return modNameArg.Name.String(), nil + } else if modNameArg, ok := callExp.ArgumentList[1].(*ast.StringLiteral); ok { + return modNameArg.Value.String(), nil + } else { + return "", errors.New("literal function definition: js functions cannot be inlined") + } + } + } + } + } + } + } + } + + return "", errors.New("js rpc function key could not be extracted: key not found") +} + func (im *RuntimeJavascriptInitModule) registerBeforeGetAccount(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "getaccount") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeGetAccount", "getaccount") } func (im *RuntimeJavascriptInitModule) registerAfterGetAccount(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "getaccount") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterGetAccount", "getaccount") } func (im *RuntimeJavascriptInitModule) registerBeforeUpdateAccount(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "updateaccount") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeUpdateAccount", "updateaccount") } func (im *RuntimeJavascriptInitModule) registerAfterUpdateAccount(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "updateaccount") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterUpdateAccount", "updateaccount") } func (im *RuntimeJavascriptInitModule) registerBeforeAuthenticateApple(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "authenticateapple") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeAuthenticateApple", "authenticateapple") } func (im *RuntimeJavascriptInitModule) registerAfterAuthenticateApple(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "authenticateapple") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterAuthenticateApple", "authenticateapple") } func (im *RuntimeJavascriptInitModule) registerBeforeAuthenticateCustom(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "authenticatecustom") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeAuthenticateCustom", "authenticatecustom") } func (im *RuntimeJavascriptInitModule) registerAfterAuthenticateCustom(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "authenticatecustom") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterAuthenticateCustom", "authenticatecustom") } func (im *RuntimeJavascriptInitModule) registerBeforeAuthenticateDevice(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "authenticatedevice") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeAuthenticateDevice", "authenticatedevice") } func (im *RuntimeJavascriptInitModule) registerAfterAuthenticateDevice(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "authenticatedevice") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterAuthenticateDevice", "authenticatedevice") } func (im *RuntimeJavascriptInitModule) registerBeforeAuthenticateEmail(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "authenticateemail") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeAuthenticateEmail", "authenticateemail") } func (im *RuntimeJavascriptInitModule) registerAfterAuthenticateEmail(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "authenticateemail") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterAuthenticateEmail", "authenticateemail") } func (im *RuntimeJavascriptInitModule) registerBeforeAuthenticateFacebook(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "authenticatefacebook") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeAuthenticateFacebook", "authenticatefacebook") } func (im *RuntimeJavascriptInitModule) registerAfterAuthenticateFacebook(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "authenticatefacebook") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterAuthenticateFacebook", "authenticatefacebook") } func (im *RuntimeJavascriptInitModule) registerBeforeAuthenticateFacebookInstantGame(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "authenticatefacebookinstantgame") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeAuthenticateFacebookInstantGame", "authenticatefacebookinstantgame") } func (im *RuntimeJavascriptInitModule) registerAfterAuthenticateFacebookInstantGame(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "authenticatefacebookinstantgame") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterAuthenticateFacebookInstantGame", "authenticatefacebookinstantgame") } func (im *RuntimeJavascriptInitModule) registerBeforeAuthenticateGameCenter(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "authenticategamecenter") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeAuthenticateGameCenter", "authenticategamecenter") } func (im *RuntimeJavascriptInitModule) registerAfterAuthenticateGameCenter(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "authenticategamecenter") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterAuthenticateGameCenter", "authenticategamecenter") } func (im *RuntimeJavascriptInitModule) registerBeforeAuthenticateGoogle(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "authenticategoogle") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeAuthenticateGoogle", "authenticategoogle") } func (im *RuntimeJavascriptInitModule) registerAfterAuthenticateGoogle(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "authenticategoogle") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterAuthenticateGoogle", "authenticategoogle") } func (im *RuntimeJavascriptInitModule) registerBeforeAuthenticateSteam(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "authenticatesteam") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeAuthenticateSteam", "authenticatesteam") } func (im *RuntimeJavascriptInitModule) registerAfterAuthenticateSteam(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "authenticatesteam") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterAuthenticateSteam", "authenticatesteam") } func (im *RuntimeJavascriptInitModule) registerBeforeListChannelMessages(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "listchannelmessages") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeListChannelMessages", "listchannelmessages") } func (im *RuntimeJavascriptInitModule) registerAfterListChannelMessages(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "listchannelmessages") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterListChannelMessages", "listchannelmessages") } func (im *RuntimeJavascriptInitModule) registerBeforeListFriends(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "listfriends") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeListFriends", "listfriends") } func (im *RuntimeJavascriptInitModule) registerAfterListFriends(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "listfriends") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterListFriends", "listfriends") } func (im *RuntimeJavascriptInitModule) registerBeforeAddFriends(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "addfriends") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeAddFriends", "addfriends") } func (im *RuntimeJavascriptInitModule) registerAfterAddFriends(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "addfriends") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterAddFriends", "addfriends") } func (im *RuntimeJavascriptInitModule) registerBeforeDeleteFriends(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "deletefriends") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeDeleteFriends", "deletefriends") } func (im *RuntimeJavascriptInitModule) registerAfterDeleteFriends(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "deletefriends") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterDeleteFriends", "deletefriends") } func (im *RuntimeJavascriptInitModule) registerBeforeBlockFriends(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "blockfriends") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeBlockFriends", "blockfriends") } func (im *RuntimeJavascriptInitModule) registerAfterBlockFriends(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "blockfriends") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterBlockFriends", "blockfriends") } func (im *RuntimeJavascriptInitModule) registerBeforeImportFacebookFriends(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "importfacebookfriends") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeImportFacebookFriends", "importfacebookfriends") } func (im *RuntimeJavascriptInitModule) registerAfterImportFacebookFriends(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "importfacebookfriends") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterImportFacebookFriends", "importfacebookfriends") } func (im *RuntimeJavascriptInitModule) registerBeforeCreateGroup(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "creategroup") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeCreateGroup", "creategroup") } func (im *RuntimeJavascriptInitModule) registerAfterCreateGroup(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "creategroup") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterCreateGroup", "creategroup") } func (im *RuntimeJavascriptInitModule) registerBeforeUpdateGroup(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "updategroup") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeUpdateGroup", "updategroup") } func (im *RuntimeJavascriptInitModule) registerAfterUpdateGroup(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "updategroup") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterUpdateGroup", "updategroup") } func (im *RuntimeJavascriptInitModule) registerBeforeDeleteGroup(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "deletegroup") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeDeleteGroup", "deletegroup") } func (im *RuntimeJavascriptInitModule) registerAfterDeleteGroup(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "deletegroup") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterDeleteGroup", "deletegroup") } func (im *RuntimeJavascriptInitModule) registerBeforeJoinGroup(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "joingroup") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeJoinGroup", "joingroup") } func (im *RuntimeJavascriptInitModule) registerAfterJoinGroup(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "joingroup") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterJoinGroup", "joingroup") } func (im *RuntimeJavascriptInitModule) registerBeforeLeaveGroup(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "leavegroup") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeLeaveGroup", "leavegroup") } func (im *RuntimeJavascriptInitModule) registerAfterLeaveGroup(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "leavegroup") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterLeaveGroup", "leavegroup") } func (im *RuntimeJavascriptInitModule) registerBeforeAddGroupUsers(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "addgroupusers") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeAddGroupUsers", "addgroupusers") } func (im *RuntimeJavascriptInitModule) registerAfterAddGroupUsers(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "addgroupusers") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterAddGroupUsers", "addgroupusers") } func (im *RuntimeJavascriptInitModule) registerBeforeBanGroupUsers(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "bangroupusers") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeBanGroupUsers", "bangroupusers") } func (im *RuntimeJavascriptInitModule) registerAfterBanGroupUsers(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "bangroupusers") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterBanGroupUsers", "bangroupusers") } func (im *RuntimeJavascriptInitModule) registerBeforeKickGroupUsers(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "kickgroupusers") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeKickGroupUsers", "kickgroupusers") } func (im *RuntimeJavascriptInitModule) registerAfterKickGroupUsers(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "kickgroupusers") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterKickGroupUsers", "kickgroupusers") } func (im *RuntimeJavascriptInitModule) registerBeforePromoteGroupUsers(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "promotegroupusers") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforePromoteGroupUsers", "promotegroupusers") } func (im *RuntimeJavascriptInitModule) registerAfterPromoteGroupUsers(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "promotegroupusers") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterPromoteGroupUsers", "promotegroupusers") } func (im *RuntimeJavascriptInitModule) registerBeforeDemoteGroupUsers(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "demotegroupusers") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeDemoteGroupUsers", "demotegroupusers") } func (im *RuntimeJavascriptInitModule) registerAfterDemoteGroupUsers(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "demotegroupusers") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterDemoteGroupUsers", "demotegroupusers") } func (im *RuntimeJavascriptInitModule) registerBeforeListGroupUsers(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "listgroupusers") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeListGroupUsers", "listgroupusers") } func (im *RuntimeJavascriptInitModule) registerAfterListGroupUsers(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "listgroupusers") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterListGroupUsers", "listgroupusers") } func (im *RuntimeJavascriptInitModule) registerBeforeListUserGroups(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "listusergroups") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeListUserGroups", "listusergroups") } func (im *RuntimeJavascriptInitModule) registerAfterListUserGroups(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "listusergroups") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterListUserGroups", "listusergroups") } func (im *RuntimeJavascriptInitModule) registerBeforeListGroups(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "listgroups") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeListGroups", "listgroups") } func (im *RuntimeJavascriptInitModule) registerAfterListGroups(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "listgroups") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterListGroups", "listgroups") } func (im *RuntimeJavascriptInitModule) registerBeforeDeleteLeaderboardRecord(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "deleteleaderboardrecord") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeDeleteLeaderboardRecord", "deleteleaderboardrecord") } func (im *RuntimeJavascriptInitModule) registerAfterDeleteLeaderboardRecord(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "deleteleaderboardrecord") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterDeleteLeaderboardRecord", "deleteleaderboardrecord") } func (im *RuntimeJavascriptInitModule) registerBeforeListLeaderboardRecords(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "listleaderboardrecords") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeListLeaderboardRecords", "listleaderboardrecords") } func (im *RuntimeJavascriptInitModule) registerAfterListLeaderboardRecords(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "listleaderboardrecords") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterListLeaderboardRecords", "listleaderboardrecords") } func (im *RuntimeJavascriptInitModule) registerBeforeWriteLeaderboardRecord(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "writeleaderboardrecord") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeWriteLeaderboardRecord", "writeleaderboardrecord") } func (im *RuntimeJavascriptInitModule) registerAfterWriteLeaderboardRecord(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "writeleaderboardrecord") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterWriteLeaderboardRecord", "writeleaderboardrecord") } func (im *RuntimeJavascriptInitModule) registerBeforeListLeaderboardRecordsAroundOwner(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "listleaderboardrecordsaroundowner") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeListLeaderboardRecordsAroundOwner", "listleaderboardrecordsaroundowner") } func (im *RuntimeJavascriptInitModule) registerAfterListLeaderboardRecordsAroundOwner(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "listleaderboardrecordsaroundowner") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterListLeaderboardRecordsAroundOwner", "listleaderboardrecordsaroundowner") } func (im *RuntimeJavascriptInitModule) registerBeforeLinkApple(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "linkapple") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeLinkApple", "linkapple") } func (im *RuntimeJavascriptInitModule) registerAfterLinkApple(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "linkapple") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterLinkApple", "linkapple") } func (im *RuntimeJavascriptInitModule) registerBeforeLinkCustom(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "linkcustom") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeLinkCustom", "linkcustom") } func (im *RuntimeJavascriptInitModule) registerAfterLinkCustom(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "linkcustom") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterLinkCustom", "linkcustom") } func (im *RuntimeJavascriptInitModule) registerBeforeLinkDevice(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "linkdevice") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeLinkDevice", "linkdevice") } func (im *RuntimeJavascriptInitModule) registerAfterLinkDevice(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "linkdevice") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterLinkDevice", "linkdevice") } func (im *RuntimeJavascriptInitModule) registerBeforeLinkEmail(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "linkemail") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeLinkEmail", "linkemail") } func (im *RuntimeJavascriptInitModule) registerAfterLinkEmail(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "linkemail") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterLinkEmail", "linkemail") } func (im *RuntimeJavascriptInitModule) registerBeforeLinkFacebook(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "linkfacebook") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeLinkFacebook", "linkfacebook") } func (im *RuntimeJavascriptInitModule) registerAfterLinkFacebook(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "linkfacebook") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterLinkFacebook", "linkfacebook") } func (im *RuntimeJavascriptInitModule) registerBeforeLinkFacebookInstantGame(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "linkfacebookinstantgame") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeLinkFacebookInstantGame", "linkfacebookinstantgame") } func (im *RuntimeJavascriptInitModule) registerAfterLinkFacebookInstantGame(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "linkfacebookinstantgame") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterLinkFacebookInstantGame", "linkfacebookinstantgame") } func (im *RuntimeJavascriptInitModule) registerBeforeLinkGameCenter(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "linkgamecenter") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeLinkGameCenter", "linkgamecenter") } func (im *RuntimeJavascriptInitModule) registerAfterLinkGameCenter(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "linkgamecenter") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterLinkGameCenter", "linkgamecenter") } func (im *RuntimeJavascriptInitModule) registerBeforeLinkGoogle(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "linkgoogle") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeLinkGoogle", "linkgoogle") } func (im *RuntimeJavascriptInitModule) registerAfterLinkGoogle(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "linkgoogle") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterLinkGoogle", "linkgoogle") } func (im *RuntimeJavascriptInitModule) registerBeforeLinkSteam(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "linksteam") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeLinkSteam", "linksteam") } func (im *RuntimeJavascriptInitModule) registerAfterLinkSteam(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "linksteam") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterLinkSteam", "linksteam") } func (im *RuntimeJavascriptInitModule) registerBeforeListMatches(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "listmatches") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeListMatches", "listmatches") } func (im *RuntimeJavascriptInitModule) registerAfterListMatches(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "listmatches") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterListMatches", "listmatches") } func (im *RuntimeJavascriptInitModule) registerBeforeListNotifications(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "listnotifications") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeListNotifications", "listnotifications") } func (im *RuntimeJavascriptInitModule) registerAfterListNotifications(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "listnotifications") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterListNotifications", "listnotifications") } func (im *RuntimeJavascriptInitModule) registerBeforeDeleteNotification(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "deletenotification") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeDeleteNotification", "deletenotification") } func (im *RuntimeJavascriptInitModule) registerAfterDeleteNotification(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "deletenotification") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterDeleteNotification", "deletenotification") } func (im *RuntimeJavascriptInitModule) registerBeforeListStorageObjects(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "liststorageobjects") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeListStorageObjects", "liststorageobjects") } func (im *RuntimeJavascriptInitModule) registerAfterListStorageObjects(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "liststorageobjects") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterListStorageObjects", "liststorageobjects") } func (im *RuntimeJavascriptInitModule) registerBeforeReadStorageObjects(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "readstorageobjects") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeReadStorageObjects", "readstorageobjects") } func (im *RuntimeJavascriptInitModule) registerAfterReadStorageObjects(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "readstorageobjects") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterReadStorageObjects", "readstorageobjects") } func (im *RuntimeJavascriptInitModule) registerBeforeWriteStorageObjects(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "writestorageobjects") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeWriteStorageObjects", "writestorageobjects") } func (im *RuntimeJavascriptInitModule) registerAfterWriteStorageObjects(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "writestorageobjects") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterWriteStorageObjects", "writestorageobjects") } func (im *RuntimeJavascriptInitModule) registerBeforeDeleteStorageObjects(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "deletestorageobjects") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeDeleteStorageObjects", "deletestorageobjects") } func (im *RuntimeJavascriptInitModule) registerAfterDeleteStorageObjects(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "deletestorageobjects") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterDeleteStorageObjects", "deletestorageobjects") } func (im *RuntimeJavascriptInitModule) registerBeforeJoinTournament(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "jointournament") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeJoinTournament", "jointournament") } func (im *RuntimeJavascriptInitModule) registerAfterJoinTournament(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "jointournament") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterJoinTournament", "jointournament") } func (im *RuntimeJavascriptInitModule) registerBeforeListTournamentRecords(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "listtournamentrecords") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeListTournamentRecords", "listtournamentrecords") } func (im *RuntimeJavascriptInitModule) registerAfterListTournamentRecords(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "listtournamentrecords") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterListTournamentRecords", "listtournamentrecords") } func (im *RuntimeJavascriptInitModule) registerBeforeListTournaments(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "listtournaments") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeListTournaments", "listtournaments") } func (im *RuntimeJavascriptInitModule) registerAfterListTournaments(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "listtournaments") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterListTournaments", "listtournaments") } func (im *RuntimeJavascriptInitModule) registerBeforeWriteTournamentRecord(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "writetournamentrecord") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeWriteTournamentRecord", "writetournamentrecord") } func (im *RuntimeJavascriptInitModule) registerAfterWriteTournamentRecord(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "writetournamentrecord") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterWriteTournamentRecord", "writetournamentrecord") } func (im *RuntimeJavascriptInitModule) registerBeforeListTournamentRecordsAroundOwner(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "listtournamentrecordsaroundowner") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeListTournamentRecordsAroundOwner", "listtournamentrecordsaroundowner") } func (im *RuntimeJavascriptInitModule) registerAfterListTournamentRecordsAroundOwner(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "listtournamentrecordsaroundowner") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterListTournamentRecordsAroundOwner", "listtournamentrecordsaroundowner") } func (im *RuntimeJavascriptInitModule) registerBeforeUnlinkApple(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "unlinkapple") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeUnlinkApple", "unlinkapple") } func (im *RuntimeJavascriptInitModule) registerAfterUnlinkApple(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "unlinkapple") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterUnlinkApple", "unlinkapple") } func (im *RuntimeJavascriptInitModule) registerBeforeUnlinkCustom(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "unlinkcustom") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeUnlinkCustom", "unlinkcustom") } func (im *RuntimeJavascriptInitModule) registerAfterUnlinkCustom(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "unlinkcustom") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterUnlinkCustom", "unlinkcustom") } func (im *RuntimeJavascriptInitModule) registerBeforeUnlinkDevice(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "unlinkdevice") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeUnlinkDevice", "unlinkdevice") } func (im *RuntimeJavascriptInitModule) registerAfterUnlinkDevice(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "unlinkdevice") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterUnlinkDevice", "unlinkdevice") } func (im *RuntimeJavascriptInitModule) registerBeforeUnlinkEmail(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "unlinkemail") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeUnlinkEmail", "unlinkemail") } func (im *RuntimeJavascriptInitModule) registerAfterUnlinkEmail(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "unlinkemail") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterUnlinkEmail", "unlinkemail") } func (im *RuntimeJavascriptInitModule) registerBeforeUnlinkFacebook(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "unlinkfacebook") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeUnlinkFacebook", "unlinkfacebook") } func (im *RuntimeJavascriptInitModule) registerAfterUnlinkFacebook(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "unlinkfacebook") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterUnlinkFacebook", "unlinkfacebook") } func (im *RuntimeJavascriptInitModule) registerBeforeUnlinkFacebookInstantGame(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "unlinkfacebookinstantgame") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeUnlinkFacebookInstantGame", "unlinkfacebookinstantgame") } func (im *RuntimeJavascriptInitModule) registerAfterUnlinkFacebookInstantGame(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "unlinkfacebookinstantgame") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterUnlinkFacebookInstantGame", "unlinkfacebookinstantgame") } func (im *RuntimeJavascriptInitModule) registerBeforeUnlinkGameCenter(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "unlinkgamecenter") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeUnlinkGameCenter", "unlinkgamecenter") } func (im *RuntimeJavascriptInitModule) registerAfterUnlinkGameCenter(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "unlinkgamecenter") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterUnlinkGameCenter", "unlinkgamecenter") } func (im *RuntimeJavascriptInitModule) registerBeforeUnlinkGoogle(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "unlinkgoogle") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeUnlinkGoogle", "unlinkgoogle") } func (im *RuntimeJavascriptInitModule) registerAfterUnlinkGoogle(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "unlinkgoogle") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterUnlinkGoogle", "unlinkgoogle") } func (im *RuntimeJavascriptInitModule) registerBeforeUnlinkSteam(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "unlinksteam") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeUnlinkSteam", "unlinksteam") } func (im *RuntimeJavascriptInitModule) registerAfterUnlinkSteam(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "unlinksteam") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterUnlinkSteam", "unlinksteam") } func (im *RuntimeJavascriptInitModule) registerBeforeGetUsers(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "getusers") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeGetUsers", "getusers") } func (im *RuntimeJavascriptInitModule) registerAfterGetUsers(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "getusers") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterGetUsers", "getusers") } func (im *RuntimeJavascriptInitModule) registerBeforeEvent(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeBefore, "event") + return im.registerHook(r, RuntimeExecutionModeBefore, "registerBeforeEvent", "event") } func (im *RuntimeJavascriptInitModule) registerAfterEvent(r *goja.Runtime) func(goja.FunctionCall) goja.Value { - return im.registerReq(r, RuntimeExecutionModeAfter, "event") + return im.registerHook(r, RuntimeExecutionModeAfter, "registerAfterEvent", "event") } -func (im *RuntimeJavascriptInitModule) registerReq(r *goja.Runtime, execMode RuntimeExecutionMode, fnName string) func(goja.FunctionCall) goja.Value { +func (im *RuntimeJavascriptInitModule) registerHook(r *goja.Runtime, execMode RuntimeExecutionMode, registerFnName, fnName string) func(goja.FunctionCall) goja.Value { return func(f goja.FunctionCall) goja.Value { fn := f.Argument(0) _, ok := goja.AssertFunction(fn) @@ -810,13 +874,58 @@ func (im *RuntimeJavascriptInitModule) registerReq(r *goja.Runtime, execMode Run } lKey := strings.ToLower(API_PREFIX + fnName) - im.registerCallbackFn(execMode, lKey, fn.Export()) + + fnKey, err := im.extractHookFn(registerFnName) + if err != nil { + panic(r.NewGoError(err)) + } + im.registerCallbackFn(execMode, lKey, fnKey) im.announceCallbackFn(execMode, lKey) return goja.Undefined() } } +func (im *RuntimeJavascriptInitModule) extractHookFn(registerFnName string) (string, error) { + for _, dec := range im.ast.DeclarationList { + var fl *ast.FunctionLiteral + if varDec, ok := dec.(*ast.VariableDeclaration); ok { + fl, ok = varDec.List[0].Initializer.(*ast.FunctionLiteral) + if !ok || varDec.List[0].Name != INIT_MODULE_FN_NAME { + continue + } + } else if fd, ok := dec.(*ast.FunctionDeclaration); ok { + fl = fd.Function + if fl.Name.Name != INIT_MODULE_FN_NAME { + continue + } + } + + callerName := fl.ParameterList.List[3].Name + if l, ok := fl.Body.(*ast.BlockStatement); ok { + for _, exp := range l.List { + if expStat, ok := exp.(*ast.ExpressionStatement); ok { + if callExp, ok := expStat.Expression.(*ast.CallExpression); ok { + if callee, ok := callExp.Callee.(*ast.DotExpression); ok { + if callee.Left.(*ast.Identifier).Name == callerName && callee.Identifier.Name.String() == registerFnName { + if modNameArg, ok := callExp.ArgumentList[0].(*ast.Identifier); ok { + return modNameArg.Name.String(), nil + } else if modNameArg, ok := callExp.ArgumentList[0].(*ast.StringLiteral); ok { + return modNameArg.Value.String(), nil + } else { + return "", inlinedFunctionError + } + } + } + } + } + } + } + } + + return "", fmt.Errorf("js %s function key could not be extracted: key not found", registerFnName) +} + func (im *RuntimeJavascriptInitModule) registerRtBefore(r *goja.Runtime) func(goja.FunctionCall) goja.Value { return func(f goja.FunctionCall) goja.Value { fName := f.Argument(0) @@ -837,8 +946,12 @@ func (im *RuntimeJavascriptInitModule) registerRtBefore(r *goja.Runtime) func(go panic(r.NewTypeError("expects a function")) } + fnKey, err := im.extractRtHookFn(r, "registerRtBefore", key) + if err != nil { + panic(r.NewGoError(err)) + } lKey := strings.ToLower(RTAPI_PREFIX + key) - im.registerCallbackFn(RuntimeExecutionModeBefore, lKey, fn.Export()) + im.registerCallbackFn(RuntimeExecutionModeBefore, lKey, fnKey) im.announceCallbackFn(RuntimeExecutionModeBefore, lKey) return goja.Undefined() @@ -865,14 +978,69 @@ func (im *RuntimeJavascriptInitModule) registerRtAfter(r *goja.Runtime) func(goj panic(r.NewTypeError("expects a function")) } + fnKey, err := im.extractRtHookFn(r, "registerRtAfter", key) + if err != nil { + panic(r.NewGoError(err)) + } lKey := strings.ToLower(RTAPI_PREFIX + key) - im.registerCallbackFn(RuntimeExecutionModeAfter, lKey, fn.Export()) + im.registerCallbackFn(RuntimeExecutionModeAfter, lKey, fnKey) im.announceCallbackFn(RuntimeExecutionModeAfter, lKey) return goja.Undefined() } } +func (im *RuntimeJavascriptInitModule) extractRtHookFn(r *goja.Runtime, registerFnName, fnName string) (string, error) { + for _, dec := range im.ast.DeclarationList { + var fl *ast.FunctionLiteral + if varDec, ok := dec.(*ast.VariableDeclaration); ok { + fl, ok = varDec.List[0].Initializer.(*ast.FunctionLiteral) + if !ok || varDec.List[0].Name != INIT_MODULE_FN_NAME { + continue + } + } else if fd, ok := dec.(*ast.FunctionDeclaration); ok { + fl = fd.Function + if fl.Name.Name != INIT_MODULE_FN_NAME { + continue + } + } + + callerName := fl.ParameterList.List[3].Name + if l, ok := fl.Body.(*ast.BlockStatement); ok { + for _, exp := range l.List { + if expStat, ok := exp.(*ast.ExpressionStatement); ok { + if callExp, ok := expStat.Expression.(*ast.CallExpression); ok { + if callee, ok := callExp.Callee.(*ast.DotExpression); ok { + if callee.Left.(*ast.Identifier).Name == callerName && callee.Identifier.Name.String() == registerFnName { + if modNameArg, ok := callExp.ArgumentList[0].(*ast.Identifier); ok { + id := modNameArg.Name.String() + if r.Get(id).String() != fnName { + continue + } + } else if modNameArg, ok := callExp.ArgumentList[0].(*ast.StringLiteral); ok { + if modNameArg.Value.String() != fnName { + continue + } + } + + if modNameArg, ok := callExp.ArgumentList[1].(*ast.Identifier); ok { + return modNameArg.Name.String(), nil + } else if modNameArg, ok := callExp.ArgumentList[1].(*ast.StringLiteral); ok { + return modNameArg.Value.String(), nil + } else { + return "", inlinedFunctionError + } + } + } + } + } + } + } + } + + return "", fmt.Errorf("js realtime %s hook function key could not be extracted: key not found", registerFnName) +} + func (im *RuntimeJavascriptInitModule) registerMatchmakerMatched(r *goja.Runtime) func(goja.FunctionCall) goja.Value { return func(f goja.FunctionCall) goja.Value { fn := f.Argument(0) @@ -881,7 +1049,11 @@ func (im *RuntimeJavascriptInitModule) registerMatchmakerMatched(r *goja.Runtime panic(r.NewTypeError("expects a function")) } - im.registerCallbackFn(RuntimeExecutionModeMatchmaker, "", fn.Export()) + fnKey, err := im.extractHookFn("registerMatchmakerMatched") + if err != nil { + panic(r.NewGoError(err)) + } + im.registerCallbackFn(RuntimeExecutionModeMatchmaker, "", fnKey) im.announceCallbackFn(RuntimeExecutionModeMatchmaker, "") return goja.Undefined() @@ -896,7 +1068,11 @@ func (im *RuntimeJavascriptInitModule) registerTournamentEnd(r *goja.Runtime) fu panic(r.NewTypeError("expects a function")) } - im.registerCallbackFn(RuntimeExecutionModeTournamentEnd, "", fn.Export()) + fnKey, err := im.extractHookFn("registerTournamentEnd") + if err != nil { + panic(r.NewGoError(err)) + } + im.registerCallbackFn(RuntimeExecutionModeTournamentEnd, "", fnKey) im.announceCallbackFn(RuntimeExecutionModeTournamentEnd, "") return goja.Undefined() @@ -911,7 +1087,11 @@ func (im *RuntimeJavascriptInitModule) registerTournamentReset(r *goja.Runtime) panic(r.NewTypeError("expects a function")) } - im.registerCallbackFn(RuntimeExecutionModeTournamentReset, "", fn.Export()) + fnKey, err := im.extractHookFn("registerTournamentReset") + if err != nil { + panic(r.NewGoError(err)) + } + im.registerCallbackFn(RuntimeExecutionModeTournamentReset, "", fnKey) im.announceCallbackFn(RuntimeExecutionModeTournamentReset, "") return goja.Undefined() @@ -926,7 +1106,11 @@ func (im *RuntimeJavascriptInitModule) registerLeaderboardReset(r *goja.Runtime) panic(r.NewTypeError("expects a function")) } - im.registerCallbackFn(RuntimeExecutionModeLeaderboardReset, "", fn.Export()) + fnKey, err := im.extractHookFn("registerLeaderboardReset") + if err != nil { + panic(r.NewGoError(err)) + } + im.registerCallbackFn(RuntimeExecutionModeLeaderboardReset, "", fnKey) im.announceCallbackFn(RuntimeExecutionModeLeaderboardReset, "") return goja.Undefined() @@ -949,65 +1133,89 @@ func (im *RuntimeJavascriptInitModule) registerMatch(r *goja.Runtime) func(goja. functions := &jsMatchHandlers{} - fnValue, ok := funcMap["matchInit"] + fnValue, ok := funcMap[string(MatchInit)] if !ok { - panic(r.NewTypeError("matchInit not found")) + panic(r.NewTypeError(string(MatchInit) + " not found")) } _, ok = goja.AssertFunction(r.ToValue(fnValue)) if !ok { - panic(r.NewTypeError("matchInit value not a valid function")) + panic(r.NewTypeError(string(MatchInit) + " value not a valid function")) + } + fnKey, err := im.extractMatchFnKey(r, name, MatchInit) + if err != nil { + panic(r.NewGoError(err)) } - functions.initFn = fnValue + functions.initFn = fnKey - fnValue, ok = funcMap["matchJoinAttempt"] + fnValue, ok = funcMap[string(MatchJoinAttempt)] if !ok { - panic(r.NewTypeError("matchJoinAttempt not found")) + panic(r.NewTypeError(string(MatchJoinAttempt) + " not found")) } _, ok = goja.AssertFunction(r.ToValue(fnValue)) if !ok { - panic(r.NewTypeError("matchJoinAttempt value not a valid function")) + panic(r.NewTypeError(string(MatchJoinAttempt) + " value not a valid function")) } - functions.joinAttemptFn = fnValue + fnKey, err = im.extractMatchFnKey(r, name, MatchJoinAttempt) + if err != nil { + panic(r.NewGoError(err)) + } + functions.joinAttemptFn = fnKey - fnValue, ok = funcMap["matchJoin"] + fnValue, ok = funcMap[string(MatchJoin)] if !ok { - panic(r.NewTypeError("matchJoin not found")) + panic(r.NewTypeError(string(MatchJoin) + " not found")) } _, ok = goja.AssertFunction(r.ToValue(fnValue)) if !ok { - panic(r.NewTypeError("matchJoin value not a valid function")) + panic(r.NewTypeError(string(MatchJoin) + " value not a valid function")) + } + fnKey, err = im.extractMatchFnKey(r, name, MatchJoin) + if err != nil { + panic(r.NewGoError(err)) } - functions.joinFn = fnValue + functions.joinFn = fnKey - fnValue, ok = funcMap["matchLeave"] + fnValue, ok = funcMap[string(MatchLeave)] if !ok { - panic(r.NewTypeError("matchLeave not found")) + panic(r.NewTypeError(string(MatchLeave) + " not found")) } _, ok = goja.AssertFunction(r.ToValue(fnValue)) if !ok { - panic(r.NewTypeError("matchLeave value not a valid function")) + panic(r.NewTypeError(string(MatchLeave) + " value not a valid function")) + } + fnKey, err = im.extractMatchFnKey(r, name, MatchLeave) + if err != nil { + panic(r.NewGoError(err)) } - functions.leaveFn = fnValue + functions.leaveFn = fnKey - fnValue, ok = funcMap["matchLoop"] + fnValue, ok = funcMap[string(MatchLoop)] if !ok { - panic(r.NewTypeError("matchLoop not found")) + panic(r.NewTypeError(string(MatchLoop) + " not found")) } _, ok = goja.AssertFunction(r.ToValue(fnValue)) if !ok { - panic(r.NewTypeError("matchLoop value not a valid function")) + panic(r.NewTypeError(string(MatchLoop) + " value not a valid function")) } - functions.loopFn = fnValue + fnKey, err = im.extractMatchFnKey(r, name, MatchLoop) + if err != nil { + panic(r.NewGoError(err)) + } + functions.loopFn = fnKey - fnValue, ok = funcMap["matchTerminate"] + fnValue, ok = funcMap[string(MatchTerminate)] if !ok { - panic(r.NewTypeError("matchTerminate not found")) + panic(r.NewTypeError(string(MatchTerminate) + " not found")) } _, ok = goja.AssertFunction(r.ToValue(fnValue)) if !ok { - panic(r.NewTypeError("matchTerminate value not a valid function")) + panic(r.NewTypeError(string(MatchTerminate) + " value not a valid function")) + } + fnKey, err = im.extractMatchFnKey(r, name, MatchTerminate) + if err != nil { + panic(r.NewGoError(err)) } - functions.terminateFn = fnValue + functions.terminateFn = fnKey im.MatchCallbacks.Add(name, functions) @@ -1015,6 +1223,76 @@ func (im *RuntimeJavascriptInitModule) registerMatch(r *goja.Runtime) func(goja. } } +type MatchFnId string + +const ( + MatchInit MatchFnId = "matchInit" + MatchJoinAttempt = "matchJoinAttempt" + MatchJoin = "matchJoin" + MatchLeave = "matchLeave" + MatchLoop = "matchLoop" + MatchTerminate = "matchTerminate" +) + +func (im *RuntimeJavascriptInitModule) extractMatchFnKey(r *goja.Runtime, modName string, id MatchFnId) (string, error) { + for _, dec := range im.ast.DeclarationList { + var fl *ast.FunctionLiteral + if varDec, ok := dec.(*ast.VariableDeclaration); ok { + fl, ok = varDec.List[0].Initializer.(*ast.FunctionLiteral) + if !ok || varDec.List[0].Name != INIT_MODULE_FN_NAME { + continue + } + } else if fd, ok := dec.(*ast.FunctionDeclaration); ok { + fl = fd.Function + if fl.Name.Name != INIT_MODULE_FN_NAME { + continue + } + } + + callerName := fl.ParameterList.List[3].Name + if l, ok := fl.Body.(*ast.BlockStatement); ok { + for _, exp := range l.List { + if expStat, ok := exp.(*ast.ExpressionStatement); ok { + if callExp, ok := expStat.Expression.(*ast.CallExpression); ok { + if callee, ok := callExp.Callee.(*ast.DotExpression); ok { + if callee.Left.(*ast.Identifier).Name == callerName && callee.Identifier.Name == "registerMatch" { + if modNameArg, ok := callExp.ArgumentList[0].(*ast.Identifier); ok { + id := modNameArg.Name.String() + if r.Get(id).String() != modName { + continue + } + } else if modNameArg, ok := callExp.ArgumentList[0].(*ast.StringLiteral); ok { + if modNameArg.Value.String() != modName { + continue + } + } + + if obj, ok := callExp.ArgumentList[1].(*ast.ObjectLiteral); ok { + for _, prop := range obj.Value { + key, _ := prop.Key.(*ast.StringLiteral) + if key.Literal == string(id) { + if sl, ok := prop.Value.(*ast.StringLiteral); ok { + return sl.Literal, nil + } else if id, ok := prop.Value.(*ast.Identifier); ok { + return id.Name.String(), nil + } else { + return "", inlinedFunctionError + } + } + } + } + break + } + } + } + } + } + } + } + + return "", fmt.Errorf("js match handler %s function key could not be extracted: key not found", id) +} + func (im *RuntimeJavascriptInitModule) registerCallbackFn(mode RuntimeExecutionMode, key string, fn interface{}) { switch mode { case RuntimeExecutionModeRPC: diff --git a/server/runtime_javascript_match_core.go b/server/runtime_javascript_match_core.go index 49cbec81d..5aca8beee 100644 --- a/server/runtime_javascript_match_core.go +++ b/server/runtime_javascript_match_core.go @@ -58,11 +58,12 @@ type RuntimeJavaScriptMatchCore struct { dispatcher goja.Value nakamaModule goja.Value loggerModule goja.Value + program *goja.Program // ctxCancelFn context.CancelFunc } -func NewRuntimeJavascriptMatchCore(logger *zap.Logger, module string, db *sql.DB, jsonpbMarshaler *jsonpb.Marshaler, jsonpbUnmarshaler *jsonpb.Unmarshaler, config Config, socialClient *social.Client, leaderboardCache LeaderboardCache, rankCache LeaderboardRankCache, localCache *RuntimeJavascriptLocalCache, leaderboardScheduler LeaderboardScheduler, sessionRegistry SessionRegistry, matchRegistry MatchRegistry, tracker Tracker, streamManager StreamManager, router MessageRouter, matchCreateFn RuntimeMatchCreateFunction, eventFn RuntimeEventCustomFunction, id uuid.UUID, node string, stopped *atomic.Bool, matchHandlers *jsMatchHandlers) (RuntimeMatchCore, error) { +func NewRuntimeJavascriptMatchCore(logger *zap.Logger, module string, db *sql.DB, jsonpbMarshaler *jsonpb.Marshaler, jsonpbUnmarshaler *jsonpb.Unmarshaler, config Config, socialClient *social.Client, leaderboardCache LeaderboardCache, rankCache LeaderboardRankCache, localCache *RuntimeJavascriptLocalCache, leaderboardScheduler LeaderboardScheduler, sessionRegistry SessionRegistry, matchRegistry MatchRegistry, tracker Tracker, streamManager StreamManager, router MessageRouter, matchCreateFn RuntimeMatchCreateFunction, eventFn RuntimeEventCustomFunction, id uuid.UUID, node string, stopped *atomic.Bool, matchHandlers *jsMatchHandlers, modCache *RuntimeJSModuleCache) (RuntimeMatchCore, error) { runtime := goja.New() jsLogger := NewJsLogger(logger) @@ -79,6 +80,8 @@ func NewRuntimeJavascriptMatchCore(logger *zap.Logger, module string, db *sql.DB logger.Fatal("Failed to initialize JavaScript runtime", zap.Error(err)) } + runtime.RunProgram(modCache.Modules[modCache.Names[0]].Program) + ctx := NewRuntimeJsInitContext(runtime, node, config.GetRuntime().Environment) ctx.Set(__RUNTIME_JAVASCRIPT_CTX_MODE, RuntimeExecutionModeMatch) ctx.Set(__RUNTIME_JAVASCRIPT_CTX_MATCH_ID, fmt.Sprintf("%v.%v", id.String(), node)) @@ -88,12 +91,12 @@ func NewRuntimeJavascriptMatchCore(logger *zap.Logger, module string, db *sql.DB // goCtx, ctxCancelFn := context.WithCancel(context.Background()) // vm.SetContext(goCtx) - initFn, _ := goja.AssertFunction(runtime.ToValue(matchHandlers.initFn)) - joinAttemptFn, _ := goja.AssertFunction(runtime.ToValue(matchHandlers.joinAttemptFn)) - joinFn, _ := goja.AssertFunction(runtime.ToValue(matchHandlers.joinFn)) - leaveFn, _ := goja.AssertFunction(runtime.ToValue(matchHandlers.leaveFn)) - loopFn, _ := goja.AssertFunction(runtime.ToValue(matchHandlers.loopFn)) - terminateFn, _ := goja.AssertFunction(runtime.ToValue(matchHandlers.terminateFn)) + initFn, _ := goja.AssertFunction(runtime.Get(matchHandlers.initFn.(string))) + joinAttemptFn, _ := goja.AssertFunction(runtime.Get(matchHandlers.joinAttemptFn.(string))) + joinFn, _ := goja.AssertFunction(runtime.Get(matchHandlers.joinFn.(string))) + leaveFn, _ := goja.AssertFunction(runtime.Get(matchHandlers.leaveFn.(string))) + loopFn, _ := goja.AssertFunction(runtime.Get(matchHandlers.loopFn.(string))) + terminateFn, _ := goja.AssertFunction(runtime.Get(matchHandlers.terminateFn.(string))) core := &RuntimeJavaScriptMatchCore{ logger: logger, -- GitLab