Skip to content

Commit

Permalink
Add PromiseRejectionHandler
Browse files Browse the repository at this point in the history
This just logs every time a promise gets rejected but has not reject
handler (yet).

The message is basically the one firefox gives.

The simplest variant of #2318
  • Loading branch information
mstoykov committed Jan 6, 2022
1 parent 9d6adcc commit 63b072a
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 0 deletions.
22 changes: 22 additions & 0 deletions js/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,28 @@ func (b *Bundle) instantiate(logger logrus.FieldLogger, rt *goja.Runtime, init *
}
rt.Set("__ENV", env)
rt.Set("__VU", vuID)
rt.SetPromiseRejectionTracker(func(p *goja.Promise, op goja.PromiseRejectionOperation) {
// TODO this only handles the case where a promise get's rejected without having a reject handler added.
// But the other case where for an already rejected promise (one that this call has already handled)
// there is now a reject handler attached is not handled.
//
// More complete implementation might need to wait for some time, the end of an iteration,
// some other event before logging a "rejection" that never got "handled"
//
// Read Notes on https://tc39.es/ecma262/#sec-host-promise-rejection-tracker
// see issue https://github.com/grafana/k6/issues/2318 for more info
if op == goja.PromiseRejectionReject {
frames := rt.CaptureCallStack(20, nil)
buf := &bytes.Buffer{}
for _, frame := range frames {
frame.Write(buf)
buf.WriteRune('\n')
}

logger.Warnf("Uncaught (in Promise) %s\n %s", p.Result(), buf.String())
}
})

rt.Set("console", common.Bind(rt, newConsole(logger), init.ctxPtr))

if init.compatibilityMode == lib.CompatibilityModeExtended {
Expand Down
30 changes: 30 additions & 0 deletions js/bundle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -976,3 +976,33 @@ func TestBundleMakeArchive(t *testing.T) {
})
}
}

func TestPromiseRejectionHandler(t *testing.T) {
t.Parallel()
logger := logrus.New()
logger.SetLevel(logrus.InfoLevel)
logger.Out = ioutil.Discard
hook := testutils.SimpleLogrusHook{
HookedLevels: []logrus.Level{logrus.WarnLevel, logrus.InfoLevel, logrus.ErrorLevel, logrus.FatalLevel, logrus.PanicLevel},
}
logger.AddHook(&hook)
_, err := getSimpleBundle(t, "/script.js", `
export let options = {
vus: 5,
teardownTimeout: '1s',
};
let val = true;
Promise.reject("here").catch((l) => console.log("caught", l));
export default function() {}
`, logger)
require.NoError(t, err)

entries := hook.Drain()
require.Len(t, entries, 2)
first := entries[0]
assert.Equal(t, logrus.WarnLevel, first.Level)
assert.Contains(t, first.Message, "Uncaught (in Promise) here")
second := entries[1]
assert.Equal(t, logrus.InfoLevel, second.Level)
assert.Contains(t, second.Message, "caught here")
}

0 comments on commit 63b072a

Please sign in to comment.