Skip to content

Commit

Permalink
Improve error recovery (#705)
Browse files Browse the repository at this point in the history
* feat: improve error recovery

* fix: only coerce to error if not nil

* refactor: move ErrorToJSError to wasm_utils

* refactor: do not transform stacktraces

* Update spicy-ways-sing.md

* Update utils.go

* chore: remove unused imports

Co-authored-by: Nate Moore <[email protected]>
  • Loading branch information
natemoo-re and natemoo-re authored Jan 17, 2023
1 parent 193064f commit 1adac72
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/spicy-ways-sing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@astrojs/compiler': minor
---

Improve error recovery when using the `transform` function. The compiler will now properly reject the promise with a useful message and stacktrace rather than print internal errors to stdout.
16 changes: 12 additions & 4 deletions cmd/astro-wasm/astro-wasm.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,15 +260,23 @@ func Transform() any {
h := handler.NewHandler(source, transformOptions.Filename)

styleError := []string{}
handler := js.FuncOf(func(this js.Value, args []js.Value) any {
promiseHandle := js.FuncOf(func(this js.Value, args []js.Value) any {
resolve := args[0]
reject := args[1]

go func() {
var doc *astro.Node
defer func() {
if err := recover(); err != nil {
reject.Invoke(wasm_utils.ErrorToJSError(h, err.(error)))
return
}
}()

doc, err := astro.ParseWithOptions(strings.NewReader(source), astro.ParseOptionWithHandler(h))
if err != nil {
fmt.Println(err)
reject.Invoke(wasm_utils.ErrorToJSError(h, err))
return
}

// Hoist styles and scripts to the top-level
Expand Down Expand Up @@ -403,11 +411,11 @@ func Transform() any {

return nil
})
defer handler.Release()
defer promiseHandle.Release()

// Create and return the Promise object
promiseConstructor := js.Global().Get("Promise")
return promiseConstructor.New(handler)
return promiseConstructor.New(promiseHandle)
})
}

Expand Down
23 changes: 23 additions & 0 deletions internal_wasm/utils/utils.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package wasm_utils

import (
"runtime/debug"
"strings"
"syscall/js"

"github.com/norunners/vert"
astro "github.com/withastro/compiler/internal"
"github.com/withastro/compiler/internal/handler"
)

// See https://stackoverflow.com/questions/68426700/how-to-wait-a-js-async-function-from-golang-wasm
Expand Down Expand Up @@ -50,3 +54,22 @@ func GetAttrs(n *astro.Node) js.Value {
}
return attrs
}

type JSError struct {
Message string `js:"message"`
Stack string `js:"stack"`
}

func (err *JSError) Value() js.Value {
return vert.ValueOf(err).Value
}

func ErrorToJSError(h *handler.Handler, err error) js.Value {
stack := string(debug.Stack())
message := strings.TrimSpace(err.Error())
jsError := JSError{
Message: message,
Stack: stack,
}
return jsError.Value()
}

0 comments on commit 1adac72

Please sign in to comment.