Skip to content

Commit

Permalink
Merge aa208f8 into 0b1fe61
Browse files Browse the repository at this point in the history
  • Loading branch information
mstoykov authored Mar 6, 2023
2 parents 0b1fe61 + aa208f8 commit f40bcd8
Show file tree
Hide file tree
Showing 8 changed files with 519 additions and 394 deletions.
301 changes: 156 additions & 145 deletions js/bundle.go

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions js/bundle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,8 @@ func TestNewBundle(t *testing.T) {
t.Parallel()
b, err := getSimpleBundle(t, "-", `export default function() {};`)
require.NoError(t, err)
assert.Equal(t, "file://-", b.Filename.String())
assert.Equal(t, "file:///", b.BaseInitContext.pwd.String())
assert.Equal(t, "file://-", b.sourceData.URL.String())
assert.Equal(t, "file:///", b.pwd.String())
})
t.Run("CompatibilityMode", func(t *testing.T) {
t.Parallel()
Expand Down
70 changes: 70 additions & 0 deletions js/cjsmodule.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package js

import (
"fmt"
"net/url"

"github.com/dop251/goja"
"go.k6.io/k6/js/compiler"
"go.k6.io/k6/js/modules"
)

// cjsModule represents a commonJS module
type cjsModule struct {
prg *goja.Program
url *url.URL
}

var _ module = &cjsModule{}

type cjsModuleInstance struct {
mod *cjsModule
moduleObj *goja.Object
vu modules.VU
}

func (c *cjsModule) Instantiate(vu modules.VU) moduleInstance {
return &cjsModuleInstance{vu: vu, mod: c}
}

func (c *cjsModuleInstance) execute() error {
rt := c.vu.Runtime()
exports := rt.NewObject()
c.moduleObj = rt.NewObject()
err := c.moduleObj.Set("exports", exports)
if err != nil {
return fmt.Errorf("error while getting ready to import commonJS, couldn't set exports property of module: %w",
err)
}

// Run the program.
f, err := rt.RunProgram(c.mod.prg)
if err != nil {
return err
}
if call, ok := goja.AssertFunction(f); ok {
if _, err = call(exports, c.moduleObj, exports); err != nil {
return err
}
}

return nil
}

func (c *cjsModuleInstance) exports() *goja.Object {
exportsV := c.moduleObj.Get("exports")
if goja.IsNull(exportsV) || goja.IsUndefined(exportsV) {
return nil
}
return exportsV.ToObject(c.vu.Runtime())
}

type cjsModuleLoader func(specifier *url.URL, name string) (*cjsModule, error)

func cjsmoduleFromString(fileURL *url.URL, data []byte, c *compiler.Compiler) (*cjsModule, error) {
pgm, _, err := c.Compile(string(data), fileURL.String(), false)
if err != nil {
return nil, err
}
return &cjsModule{prg: pgm, url: fileURL}, nil
}
93 changes: 93 additions & 0 deletions js/gomodule.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package js

import (
"github.com/dop251/goja"
"go.k6.io/k6/js/modules"
)

// baseGoModule is a go module that does not implement modules.Module interface
// TODO maybe depracate those in the future
type baseGoModule struct {
mod interface{}
}

var _ module = &baseGoModule{}

func (b *baseGoModule) Instantiate(vu modules.VU) moduleInstance {
return &baseGoModuleInstance{mod: b.mod, vu: vu}
}

type baseGoModuleInstance struct {
mod interface{}
vu modules.VU
exportsO *goja.Object // this is so we only initialize the exports once per instance
}

func (b *baseGoModuleInstance) execute() error {
return nil
}

func (b *baseGoModuleInstance) exports() *goja.Object {
if b.exportsO == nil {
// TODO check this does not panic a lot
rt := b.vu.Runtime()
b.exportsO = rt.ToValue(b.mod).ToObject(rt)
}
return b.exportsO
}

// goModule is a go module which implements modules.Module
type goModule struct {
modules.Module
}

var _ module = &goModule{}

func (g *goModule) Instantiate(vu modules.VU) moduleInstance {
return &goModuleInstance{vu: vu, module: g}
}

type goModuleInstance struct {
modules.Instance
module *goModule
vu modules.VU
exportsO *goja.Object // this is so we only initialize the exports once per instance
}

var _ moduleInstance = &goModuleInstance{}

func (gi *goModuleInstance) execute() error {
gi.Instance = gi.module.NewModuleInstance(gi.vu)
return nil
}

func (gi *goModuleInstance) exports() *goja.Object {
if gi.exportsO == nil {
rt := gi.vu.Runtime()
gi.exportsO = rt.ToValue(toESModuleExports(gi.Instance.Exports())).ToObject(rt)
}
return gi.exportsO
}

func toESModuleExports(exp modules.Exports) interface{} {
if exp.Named == nil {
return exp.Default
}
if exp.Default == nil {
return exp.Named
}

result := make(map[string]interface{}, len(exp.Named)+2)

for k, v := range exp.Named {
result[k] = v
}
// Maybe check that those weren't set
result["default"] = exp.Default
// this so babel works with the `default` when it transpiles from ESM to commonjs.
// This should probably be removed once we have support for ESM directly. So that require doesn't get support for
// that while ESM has.
result["__esModule"] = true

return result
}
Loading

0 comments on commit f40bcd8

Please sign in to comment.