Skip to content

Commit

Permalink
Merge 27973ce into 47c5bb0
Browse files Browse the repository at this point in the history
  • Loading branch information
mstoykov committed Feb 29, 2024
2 parents 47c5bb0 + 27973ce commit ab63cf5
Show file tree
Hide file tree
Showing 38 changed files with 3,311 additions and 875 deletions.
22 changes: 11 additions & 11 deletions cmd/tests/cmd_run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -944,8 +944,8 @@ func TestAbortedByScriptSetupErrorWithDependency(t *testing.T) {
if runtime.GOOS == "windows" {
rootPath += "c:/"
}
assert.Contains(t, stdout, `level=error msg="Error: baz\n\tat baz (`+rootPath+`test/bar.js:6:9(3))\n\tat `+
rootPath+`test/bar.js:3:3(3)\n\tat setup (`+rootPath+`test/test.js:5:3(9))\n" hint="script exception"`)
assert.Contains(t, stdout, `level=error msg="Error: baz\n\tat baz (`+rootPath+`test/bar.js:6:10(3))\n\tat default (`+
rootPath+`test/bar.js:3:7(3))\n\tat setup (`+rootPath+`test/test.js:5:7(8))\n" hint="script exception"`)
assert.Contains(t, stdout, `level=debug msg="Sending test finished" output=cloud ref=123 run_status=7 tainted=false`)
assert.Contains(t, stdout, "bogus summary")
}
Expand Down Expand Up @@ -2106,10 +2106,10 @@ func TestEventSystemError(t *testing.T) {
"got event Init with data '<nil>'",
"got event TestStart with data '<nil>'",
"got event IterStart with data '{Iteration:0 VUID:1 ScenarioName:default Error:<nil>}'",
"got event IterEnd with data '{Iteration:0 VUID:1 ScenarioName:default Error:test aborted: oops! at file:///-:11:16(6)}'",
"got event IterEnd with data '{Iteration:0 VUID:1 ScenarioName:default Error:test aborted: oops! at default (file:///-:11:16(5))}'",
"got event TestEnd with data '<nil>'",
"got event Exit with data '&{Error:test aborted: oops! at file:///-:11:16(6)}'",
"test aborted: oops! at file:///-:11:16(6)",
"got event Exit with data '&{Error:test aborted: oops! at default (file:///-:11:16(5))}'",
"test aborted: oops! at default (file:///-:11:16(5))",
},
expExitCode: exitcodes.ScriptAborted,
},
Expand All @@ -2118,8 +2118,8 @@ func TestEventSystemError(t *testing.T) {
script: "undefinedVar",
expLog: []string{
"got event Exit with data '&{Error:could not initialize '-': could not load JS test " +
"'file:///-': ReferenceError: undefinedVar is not defined\n\tat file:///-:2:0(12)\n}'",
"ReferenceError: undefinedVar is not defined\n\tat file:///-:2:0(12)\n",
"'file:///-': ReferenceError: undefinedVar is not defined\n\tat file:///-:2:1(8)\n}'",
"ReferenceError: undefinedVar is not defined\n\tat file:///-:2:1(8)\n",
},
expExitCode: exitcodes.ScriptException,
},
Expand All @@ -2138,11 +2138,11 @@ func TestEventSystemError(t *testing.T) {
"got event Init with data '<nil>'",
"got event TestStart with data '<nil>'",
"got event IterStart with data '{Iteration:0 VUID:1 ScenarioName:default Error:<nil>}'",
"got event IterEnd with data '{Iteration:0 VUID:1 ScenarioName:default Error:Error: oops!\n\tat file:///-:9:11(3)\n}'",
"Error: oops!\n\tat file:///-:9:11(3)\n",
"got event IterEnd with data '{Iteration:0 VUID:1 ScenarioName:default Error:Error: oops!\n\tat default (file:///-:9:12(3))\n}'",
"Error: oops!\n\tat default (file:///-:9:12(3))\n",
"got event IterStart with data '{Iteration:1 VUID:1 ScenarioName:default Error:<nil>}'",
"got event IterEnd with data '{Iteration:1 VUID:1 ScenarioName:default Error:Error: oops!\n\tat file:///-:9:11(3)\n}'",
"Error: oops!\n\tat file:///-:9:11(3)\n",
"got event IterEnd with data '{Iteration:1 VUID:1 ScenarioName:default Error:Error: oops!\n\tat default (file:///-:9:12(3))\n}'",
"Error: oops!\n\tat default (file:///-:9:12(3))\n",
"got event TestEnd with data '<nil>'",
"got event Exit with data '&{Error:<nil>}'",
},
Expand Down
2 changes: 1 addition & 1 deletion cmd/tests/eventloop_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ func TestEventLoopDoesntCrossIterations(t *testing.T) {
eventLoopTest(t, script, func(logLines []string) {
require.Equal(t, []string{
"setTimeout 1 was stopped because the VU iteration was interrupted",
"just error\n\tat file:///-:13:4(15)\n", "1",
"just error\n\tat default (file:///-:13:5(14))\n", "1",
}, logLines)
})
}
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,5 @@ require (
gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
)

replace github.com/dop251/goja => github.com/mstoykov/goja v0.0.0-20231212144616-08f562ee86d0
9 changes: 2 additions & 7 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,9 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/dlclark/regexp2 v1.9.0 h1:pTK/l/3qYIKaRXuHnEnIf7Y5NxfRPfpb7dis6/gdlVI=
github.com/dlclark/regexp2 v1.9.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk=
github.com/dop251/goja v0.0.0-20240220182346-e401ed450204 h1:O7I1iuzEA7SG+dK8ocOBSlYAA9jBUmCYl/Qa7ey7JAM=
github.com/dop251/goja v0.0.0-20240220182346-e401ed450204/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4=
github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y=
github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
Expand Down Expand Up @@ -124,7 +119,6 @@ github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW
github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
Expand All @@ -146,6 +140,8 @@ github.com/mstoykov/atlas v0.0.0-20220811071828-388f114305dd h1:AC3N94irbx2kWGA8
github.com/mstoykov/atlas v0.0.0-20220811071828-388f114305dd/go.mod h1:9vRHVuLCjoFfE3GT06X0spdOAO+Zzo4AMjdIwUHBvAk=
github.com/mstoykov/envconfig v1.4.1-0.20220114105314-765c6d8c76f1 h1:94EkGmhXrVUEal+uLwFUf4fMXPhZpM5tYxuIsxrCCbI=
github.com/mstoykov/envconfig v1.4.1-0.20220114105314-765c6d8c76f1/go.mod h1:vk/d9jpexY2Z9Bb0uB4Ndesss1Sr0Z9ZiGUrg5o9VGk=
github.com/mstoykov/goja v0.0.0-20231212144616-08f562ee86d0 h1:AcJZgDvroNJdSX/Ip5hN0P5xhatMwmJBbLHqn3jqjME=
github.com/mstoykov/goja v0.0.0-20231212144616-08f562ee86d0/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4=
github.com/mstoykov/k6-taskqueue-lib v0.1.0 h1:M3eww1HSOLEN6rIkbNOJHhOVhlqnqkhYj7GTieiMBz4=
github.com/mstoykov/k6-taskqueue-lib v0.1.0/go.mod h1:PXdINulapvmzF545Auw++SCD69942FeNvUztaa9dVe4=
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ=
Expand Down Expand Up @@ -343,7 +339,6 @@ gopkg.in/cenkalti/backoff.v1 v1.1.0/go.mod h1:J6Vskwqd+OMVJl8C33mmtxTBs2gyzfv7UD
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/guregu/null.v3 v3.3.0 h1:8j3ggqq+NgKt/O7mbFVUFKUMWN+l1AmT5jQmJ6nPh2c=
gopkg.in/guregu/null.v3 v3.3.0/go.mod h1:E4tX2Qe3h7QdL+uZ3a0vqvYwKQsRSQKM5V4YltdgH9Y=
Expand Down
80 changes: 38 additions & 42 deletions js/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,9 @@ type BundleInstance struct {
// TODO: maybe just have a reference to the Bundle? or save and pass rtOpts?
env map[string]string

mainModuleExports *goja.Object
moduleVUImpl *moduleVUImpl
mainModule goja.ModuleRecord
mainModuleInstance goja.ModuleInstance
moduleVUImpl *moduleVUImpl
}

func (bi *BundleInstance) getCallableExport(name string) goja.Callable {
Expand All @@ -59,7 +60,7 @@ func (bi *BundleInstance) getCallableExport(name string) goja.Callable {
}

func (bi *BundleInstance) getExported(name string) goja.Value {
return bi.mainModuleExports.Get(name)
return bi.mainModuleInstance.GetBindingValue(name)
}

// NewBundle creates a new bundle from a source file and a filesystem.
Expand Down Expand Up @@ -89,7 +90,7 @@ func newBundle(
preInitState: piState,
}
c := bundle.newCompiler(piState.Logger)
bundle.ModuleResolver = modules.NewModuleResolver(getJSModules(), generateFileLoad(bundle), c)
bundle.ModuleResolver = modules.NewModuleResolver(getJSModules(), generateFileLoad(bundle), c, src.URL.JoinPath(".."))

// Instantiate the bundle into a new VM using a bound init context. This uses a context with a
// runtime, but no state, to allow module-provided types to function within the init context.
Expand All @@ -103,12 +104,12 @@ func newBundle(
},
}
vuImpl.eventLoop = eventloop.New(vuImpl)
exports, err := bundle.instantiate(vuImpl, 0)
bi, err := bundle.instantiate(vuImpl, 0)
if err != nil {
return nil, err
}

err = bundle.populateExports(updateOptions, exports)
err = bundle.populateExports(updateOptions, bi)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -165,9 +166,9 @@ func (b *Bundle) makeArchive() *lib.Archive {
}

// populateExports validates and extracts exported objects
func (b *Bundle) populateExports(updateOptions bool, exports *goja.Object) error {
for _, k := range exports.Keys() {
v := exports.Get(k)
func (b *Bundle) populateExports(updateOptions bool, bi *BundleInstance) error {
for _, k := range bi.mainModule.GetExportedNames() {
v := bi.getExported(k)
if _, ok := goja.AssertFunction(v); ok && k != consts.Options {
b.callableExports[k] = struct{}{}
continue
Expand Down Expand Up @@ -216,40 +217,34 @@ func (b *Bundle) Instantiate(ctx context.Context, vuID uint64) (*BundleInstance,
},
}
vuImpl.eventLoop = eventloop.New(vuImpl)
exports, err := b.instantiate(vuImpl, vuID)
bi, err := b.instantiate(vuImpl, vuID)
if err != nil {
return nil, err
}

bi := &BundleInstance{
Runtime: vuImpl.runtime,
env: b.preInitState.RuntimeOptions.Env,
moduleVUImpl: vuImpl,
mainModuleExports: exports,
if err = bi.manipulateOptions(b.Options); err != nil {
return nil, err
}

return bi, nil
}

func (bi *BundleInstance) manipulateOptions(options lib.Options) error {
// Grab any exported functions that could be executed. These were
// already pre-validated in cmd.validateScenarioConfig(), just get them here.
jsOptions := exports.Get(consts.Options)
jsOptions := bi.getExported(consts.Options)
var jsOptionsObj *goja.Object
if common.IsNullish(jsOptions) {
jsOptionsObj = vuImpl.runtime.NewObject()
err := exports.Set(consts.Options, jsOptionsObj)
if err != nil {
return nil, fmt.Errorf("couldn't set exported options with merged values: %w", err)
}
} else {
jsOptionsObj = jsOptions.ToObject(vuImpl.runtime)
return nil
}

jsOptionsObj = jsOptions.ToObject(bi.Runtime)
var instErr error
b.Options.ForEachSpecified("json", func(key string, val interface{}) {
options.ForEachSpecified("json", func(key string, val interface{}) {
if err := jsOptionsObj.Set(key, val); err != nil {
instErr = err
}
})

return bi, instErr
return instErr
}

func (b *Bundle) newCompiler(logger logrus.FieldLogger) *compiler.Compiler {
Expand All @@ -262,7 +257,7 @@ func (b *Bundle) newCompiler(logger logrus.FieldLogger) *compiler.Compiler {
return c
}

func (b *Bundle) instantiate(vuImpl *moduleVUImpl, vuID uint64) (*goja.Object, error) {
func (b *Bundle) instantiate(vuImpl *moduleVUImpl, vuID uint64) (*BundleInstance, error) {
rt := vuImpl.runtime
err := b.setupJSRuntime(rt, int64(vuID), b.preInitState.Logger)
if err != nil {
Expand Down Expand Up @@ -294,14 +289,23 @@ func (b *Bundle) instantiate(vuImpl *moduleVUImpl, vuID uint64) (*goja.Object, e
}
close(initDone)
}()

var exportsV goja.Value
bi := &BundleInstance{
Runtime: vuImpl.runtime,
env: b.preInitState.RuntimeOptions.Env,
moduleVUImpl: vuImpl,
}
err = common.RunWithPanicCatching(b.preInitState.Logger, rt, func() error {
return vuImpl.eventLoop.Start(func() error {
//nolint:govet // here we shadow err on purpose
var err error
exportsV, err = modSys.RunSourceData(b.sourceData)
return err

bi.mainModule, err = modSys.RunSourceData(b.sourceData)
if err != nil {
return err
}
// TODO move this here
bi.mainModuleInstance = rt.GetModuleInstance(bi.mainModule)
return nil
})
})

Expand All @@ -314,14 +318,6 @@ func (b *Bundle) instantiate(vuImpl *moduleVUImpl, vuID uint64) (*goja.Object, e
}
return nil, err
}
if common.IsNullish(exportsV) {
return nil, errors.New("exports must not be set to null or undefined")
}
exports := exportsV.ToObject(vuImpl.runtime)

if exports == nil {
return nil, errors.New("exports must be an object")
}

// If we've already initialized the original VU init context, forbid
// any subsequent VUs to open new files
Expand All @@ -331,7 +327,7 @@ func (b *Bundle) instantiate(vuImpl *moduleVUImpl, vuID uint64) (*goja.Object, e

rt.SetRandSource(common.NewRandSource())

return exports, nil
return bi, nil
}

func (b *Bundle) setupJSRuntime(rt *goja.Runtime, vuID int64, logger logrus.FieldLogger) error {
Expand Down Expand Up @@ -402,7 +398,7 @@ func (b *Bundle) setInitGlobals(rt *goja.Runtime, vu *moduleVUImpl, modSys *modu
}
// This uses the pwd from the requireImpl
pwd := impl.internal.CurrentlyRequiredModule()
return openImpl(rt, b.filesystems["file"], &pwd, filename, args...)
return openImpl(rt, b.filesystems["file"], pwd, filename, args...)
})

return func() {
Expand Down
12 changes: 3 additions & 9 deletions js/bundle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func TestNewBundle(t *testing.T) {
t.Parallel()
_, err := getSimpleBundle(t, "/script.js", "\x00")
require.NotNil(t, err)
require.Contains(t, err.Error(), "SyntaxError: file:///script.js: Unexpected character '\x00' (1:0)\n> 1 | \x00\n")
require.Contains(t, err.Error(), "file:///script.js: Line 1:1 Unexpected token ILLEGAL (and 1 more errors)")
})
t.Run("Error", func(t *testing.T) {
t.Parallel()
Expand Down Expand Up @@ -161,11 +161,6 @@ func TestNewBundle(t *testing.T) {
"InvalidCompat", "es1", `export default function() {};`,
`invalid compatibility mode "es1". Use: "extended", "base"`,
},
// ES2015 modules are not supported
{
"Modules", "base", `export default function() {};`,
"file:///script.js: Line 2:1 Unexpected reserved word (and 2 more errors)",
},
// BigInt is not supported
{
"BigInt", "base",
Expand Down Expand Up @@ -503,7 +498,6 @@ func TestNewBundleFromArchive(t *testing.T) {

checkArchive(t, arc, lib.RuntimeOptions{}, "") // default options
checkArchive(t, arc, extCompatModeRtOpts, "")
checkArchive(t, arc, baseCompatModeRtOpts, "Unexpected reserved word")
})

t.Run("es6_script_explicit", func(t *testing.T) {
Expand All @@ -514,7 +508,6 @@ func TestNewBundleFromArchive(t *testing.T) {

checkArchive(t, arc, lib.RuntimeOptions{}, "")
checkArchive(t, arc, extCompatModeRtOpts, "")
checkArchive(t, arc, baseCompatModeRtOpts, "Unexpected reserved word")
})

t.Run("es5_script_with_extended", func(t *testing.T) {
Expand All @@ -539,12 +532,14 @@ func TestNewBundleFromArchive(t *testing.T) {
checkArchive(t, arc, baseCompatModeRtOpts, "")
})

/* TODO remove completely - this no longer makes sense
t.Run("es6_archive_with_wrong_compat_mode", func(t *testing.T) {
t.Parallel()
arc, err := getArchive(t, es6Code, baseCompatModeRtOpts)
require.Error(t, err)
require.Nil(t, arc)
})
*/

t.Run("messed_up_archive", func(t *testing.T) {
t.Parallel()
Expand All @@ -553,7 +548,6 @@ func TestNewBundleFromArchive(t *testing.T) {
arc.CompatibilityMode = "blah" // intentionally break the archive
checkArchive(t, arc, lib.RuntimeOptions{}, "invalid compatibility mode") // fails when it uses the archive one
checkArchive(t, arc, extCompatModeRtOpts, "") // works when I force the compat mode
checkArchive(t, arc, baseCompatModeRtOpts, "Unexpected reserved word") // failes because of ES6
})

t.Run("script_options_dont_overwrite_metadata", func(t *testing.T) {
Expand Down

0 comments on commit ab63cf5

Please sign in to comment.