#1271·gopherjs

Function expression should be evaluated before arguments

Author: nevkontakteCreated Feb 25, 2024Updated Feb 25, 2024
Labelsbug

Consider the following snippet:

go
package main

var ok = false

func f() func(int, int) {
	ok = true
	return func(int, int) {}
}

func g() (int, int) {
	if !ok {
		panic("Bad order!")
	}
	return 0, 0
}

func main() {
	f()(g())
}

In it, the f()(g()) should be equivalent to:

go
funExpr := f()
a, b := g()
funExpr(a, b)

However, in GopherJS it is:

go
a, b := g()
funExpr := f()
funExpr(a, b)

https://gopherjs.github.io/playground/#/FMGNfOX9RA

https://go.dev/play/p/DGqo4zOvkUM

The bug is here: https://github.com/gopherjs/gopherjs/blob/e76f82360ff049505deaa7d42af04f5d67bf565b/compiler/utils.go#L119. When a function argument is another function's returned tuple, the inner function is broken out into a separate statement that's evaluated too early. To avoid that we can use ES6 spread operator and avoid a separate statement.