feat: Report native function panics as runtime errors.

Previously, you'd get an "INTERNAL ERROR: (CRASH)" with a full backtrace
and a link to file a bug against go-jsonnet.
This commit is contained in:
Rudo Thomas 2022-06-30 11:17:26 +02:00 committed by Stanisław Barzowski
parent 32b292c9cb
commit b42132a7a3
5 changed files with 30 additions and 1 deletions

View File

@ -96,6 +96,14 @@ var nativeError = &NativeFunction{
}, },
} }
var nativePanic = &NativeFunction{
Name: "nativePanic",
Params: ast.Identifiers{},
Func: func(x []interface{}) (interface{}, error) {
panic("native function panic")
},
}
type jsonnetInput struct { type jsonnetInput struct {
name string name string
input []byte input []byte
@ -136,6 +144,7 @@ func runInternalJsonnet(i jsonnetInput) jsonnetResult {
vm.NativeFunction(jsonToString) vm.NativeFunction(jsonToString)
vm.NativeFunction(nativeError) vm.NativeFunction(nativeError)
vm.NativeFunction(nativePanic)
rawAST, _, staticErr := parser.SnippetToRawAST(ast.DiagnosticFileName(i.name), "", string(i.input)) rawAST, _, staticErr := parser.SnippetToRawAST(ast.DiagnosticFileName(i.name), "", string(i.input))
if staticErr != nil { if staticErr != nil {

10
testdata/native_panic.golden vendored Normal file
View File

@ -0,0 +1,10 @@
RUNTIME ERROR: native function "nativePanic" panicked: native function panic
-------------------------------------------------
testdata/native_panic:1:1-28 $
std.native("nativePanic")()
-------------------------------------------------
During evaluation

1
testdata/native_panic.jsonnet vendored Normal file
View File

@ -0,0 +1 @@
std.native("nativePanic")()

0
testdata/native_panic.linter.golden vendored Normal file
View File

View File

@ -17,6 +17,7 @@ limitations under the License.
package jsonnet package jsonnet
import ( import (
"fmt"
"github.com/google/go-jsonnet/ast" "github.com/google/go-jsonnet/ast"
) )
@ -273,7 +274,15 @@ func (native *NativeFunction) evalCall(arguments callArguments, i *interpreter)
} }
nativeArgs = append(nativeArgs, json) nativeArgs = append(nativeArgs, json)
} }
resultJSON, err := native.Func(nativeArgs) call := func() (resultJSON interface{}, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("native function %#v panicked: %v", native.Name, r)
}
}()
return native.Func(nativeArgs)
}
resultJSON, err := call()
if err != nil { if err != nil {
return nil, i.Error(err.Error()) return nil, i.Error(err.Error())
} }