Skip to content

Commit

Permalink
Move the CompatibilityMode type to the lib package
Browse files Browse the repository at this point in the history
This was needed because if the `lib` package depended on the `js/compiler` package, any Go project imports lib would also import goja and babel...
  • Loading branch information
na-- committed Feb 7, 2020
1 parent a1f3802 commit 5047368
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 61 deletions.
6 changes: 3 additions & 3 deletions js/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ type Bundle struct {
BaseInitContext *InitContext

Env map[string]string
CompatibilityMode compiler.CompatibilityMode
CompatibilityMode lib.CompatibilityMode
}

// A BundleInstance is a self-contained instance of a Bundle.
Expand Down Expand Up @@ -198,7 +198,7 @@ func (b *Bundle) makeArchive() *lib.Archive {

// Instantiate creates a new runtime from this bundle.
func (b *Bundle) Instantiate() (bi *BundleInstance, instErr error) {
//TODO: actually use a real context here, so that the instantiation can be killed
// TODO: actually use a real context here, so that the instantiation can be killed
// Placeholder for a real context.
ctxPtr := new(context.Context)

Expand Down Expand Up @@ -244,7 +244,7 @@ func (b *Bundle) instantiate(rt *goja.Runtime, init *InitContext) error {
rt.SetFieldNameMapper(common.FieldNameMapper{})
rt.SetRandSource(common.NewRandSource())

if init.compatibilityMode == compiler.CompatibilityModeExtended {
if init.compatibilityMode == lib.CompatibilityModeExtended {
if _, err := rt.RunProgram(jslib.GetCoreJS()); err != nil {
return err
}
Expand Down
72 changes: 44 additions & 28 deletions js/bundle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import (
"time"

"github.com/dop251/goja"
"github.com/loadimpact/k6/js/compiler"
"github.com/loadimpact/k6/lib"
"github.com/loadimpact/k6/lib/consts"
"github.com/loadimpact/k6/lib/fsext"
Expand Down Expand Up @@ -114,14 +113,16 @@ func TestNewBundle(t *testing.T) {
t.Run("CompatibilityMode", func(t *testing.T) {
t.Run("Extended/ok/CoreJS", func(t *testing.T) {
rtOpts := lib.RuntimeOptions{
CompatibilityMode: null.StringFrom(compiler.CompatibilityModeExtended.String())}
CompatibilityMode: null.StringFrom(lib.CompatibilityModeExtended.String()),
}
_, err := getSimpleBundle("/script.js",
`export default function() {}; new Set([1, 2, 3, 2, 1]);`, rtOpts)
assert.NoError(t, err)
})
t.Run("Base/ok/Minimal", func(t *testing.T) {
rtOpts := lib.RuntimeOptions{
CompatibilityMode: null.StringFrom(compiler.CompatibilityModeBase.String())}
CompatibilityMode: null.StringFrom(lib.CompatibilityModeBase.String()),
}
_, err := getSimpleBundle("/script.js",
`module.exports.default = function() {};`, rtOpts)
assert.NoError(t, err)
Expand All @@ -133,19 +134,27 @@ func TestNewBundle(t *testing.T) {
code string
expErr string
}{
{"InvalidCompat", "es1", `export default function() {};`,
`invalid compatibility mode "es1". Use: "extended", "base"`},
{
"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 1:1 Unexpected reserved word"},
{
"Modules", "base", `export default function() {};`,
"file:///script.js: Line 1:1 Unexpected reserved word",
},
// Arrow functions are not supported
{"ArrowFuncs", "base",
{
"ArrowFuncs", "base",
`module.exports.default = function() {}; () => {};`,
"file:///script.js: Line 1:42 Unexpected token ) (and 1 more errors)"},
"file:///script.js: Line 1:42 Unexpected token ) (and 1 more errors)",
},
// ES2015 objects polyfilled by core.js are not supported
{"CoreJS", "base",
{
"CoreJS", "base",
`module.exports.default = function() {}; new Set([1, 2, 3, 2, 1]);`,
"ReferenceError: Set is not defined at file:///script.js:1:45(5)"},
"ReferenceError: Set is not defined at file:///script.js:1:45(5)",
},
}

for _, tc := range testCases {
Expand Down Expand Up @@ -386,7 +395,6 @@ func TestNewBundle(t *testing.T) {
assert.Equal(t, b.Options.TLSVersion.Min, lib.TLSVersion(tls.VersionSSL30))
assert.Equal(t, b.Options.TLSVersion.Max, lib.TLSVersion(tls.VersionSSL30))
}

})
})
t.Run("Thresholds", func(t *testing.T) {
Expand Down Expand Up @@ -424,10 +432,10 @@ func TestNewBundleFromArchive(t *testing.T) {
{"", `
export let options = { vus: 12345 };
export default function() { return "hi!"; };`},
{compiler.CompatibilityModeExtended.String(), `
{lib.CompatibilityModeExtended.String(), `
export let options = { vus: 12345 };
export default function() { return "hi!"; };`},
{compiler.CompatibilityModeBase.String(), `
{lib.CompatibilityModeBase.String(), `
module.exports.options = { vus: 12345 };
module.exports.default = function() { return "hi!" };`},
}
Expand All @@ -445,7 +453,7 @@ func TestNewBundleFromArchive(t *testing.T) {
assert.Equal(t, lib.Options{VUs: null.IntFrom(12345)}, b.Options)
expCM := tc.compatMode
if expCM == "" {
expCM = compiler.CompatibilityModeExtended.String()
expCM = lib.CompatibilityModeExtended.String()
}
assert.Equal(t, expCM, b.CompatibilityMode.String())

Expand All @@ -466,14 +474,18 @@ func TestNewBundleFromArchive(t *testing.T) {
compatMode, code, expErr string
}{
// Incompatible mode
{compiler.CompatibilityModeBase.String(), `
{
lib.CompatibilityModeBase.String(), `
export let options = { vus: 12345 };
export default function() { return "hi!"; };`,
"file://script.js: Line 2:5 Unexpected reserved word (and 2 more errors)"},
{"wrongcompat", `
"file://script.js: Line 2:5 Unexpected reserved word (and 2 more errors)",
},
{
"wrongcompat", `
export let options = { vus: 12345 };
export default function() { return "hi!"; };`,
`invalid compatibility mode "wrongcompat". Use: "extended", "base"`},
`invalid compatibility mode "wrongcompat". Use: "extended", "base"`,
},
}

for _, tc := range testCases {
Expand All @@ -488,7 +500,7 @@ func TestNewBundleFromArchive(t *testing.T) {
}

func TestOpen(t *testing.T) {
var testCases = [...]struct {
testCases := [...]struct {
name string
openPath string
pwd string
Expand Down Expand Up @@ -588,16 +600,16 @@ func TestOpen(t *testing.T) {
for _, tCase := range testCases {
tCase := tCase

var testFunc = func(t *testing.T) {
var openPath = tCase.openPath
testFunc := func(t *testing.T) {
openPath := tCase.openPath
// if fullpath prepend prefix
if openPath != "" && (openPath[0] == '/' || openPath[0] == '\\') {
openPath = filepath.Join(prefix, openPath)
}
if isWindows {
openPath = strings.Replace(openPath, `\`, `\\`, -1)
}
var pwd = tCase.pwd
pwd := tCase.pwd
if pwd == "" {
pwd = "/path/to/"
}
Expand Down Expand Up @@ -731,22 +743,26 @@ func TestBundleEnv(t *testing.T) {

func TestBundleMakeArchive(t *testing.T) {
testCases := []struct {
cm compiler.CompatibilityMode
cm lib.CompatibilityMode
script string
exclaim string
}{
{compiler.CompatibilityModeExtended, `
{
lib.CompatibilityModeExtended, `
import exclaim from "./exclaim.js";
export let options = { vus: 12345 };
export let file = open("./file.txt");
export default function() { return exclaim(file); };`,
`export default function(s) { return s + "!" };`},
{compiler.CompatibilityModeBase, `
`export default function(s) { return s + "!" };`,
},
{
lib.CompatibilityModeBase, `
var exclaim = require("./exclaim.js");
module.exports.options = { vus: 12345 };
module.exports.file = open("./file.txt");
module.exports.default = function() { return exclaim(module.exports.file); };`,
`module.exports.default = function(s) { return s + "!" };`},
`module.exports.default = function(s) { return s + "!" };`,
},
}

for _, tc := range testCases {
Expand Down
19 changes: 4 additions & 15 deletions js/compiler/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
rice "github.com/GeertJohan/go.rice"
"github.com/dop251/goja"
"github.com/dop251/goja/parser"
"github.com/loadimpact/k6/lib"
"github.com/mitchellh/mapstructure"
"github.com/sirupsen/logrus"
)
Expand All @@ -48,18 +49,6 @@ var (
globalBabel *babel // nolint:gochecknoglobals
)

// CompatibilityMode specifies the JS compatibility mode
// nolint:lll
//go:generate enumer -type=CompatibilityMode -transform=snake -trimprefix CompatibilityMode -output compatibility_mode_gen.go
type CompatibilityMode uint8

const (
// CompatibilityModeExtended achieves ES6+ compatibility with Babel and core.js
CompatibilityModeExtended CompatibilityMode = iota + 1
// CompatibilityModeBase is standard goja ES5.1+
CompatibilityModeBase
)

// A Compiler compiles JavaScript source code (ES5.1 or ES6) into a goja.Program
type Compiler struct{}

Expand All @@ -80,11 +69,11 @@ func (c *Compiler) Transform(src, filename string) (code string, srcmap *SourceM

// Compile the program in the given CompatibilityMode, optionally running pre and post code.
func (c *Compiler) Compile(src, filename, pre, post string,
strict bool, compatMode CompatibilityMode) (*goja.Program, string, error) {
strict bool, compatMode lib.CompatibilityMode) (*goja.Program, string, error) {
code := pre + src + post
ast, err := parser.ParseFile(nil, filename, code, 0)
if err != nil {
if compatMode == CompatibilityModeExtended {
if compatMode == lib.CompatibilityModeExtended {
code, _, err = c.Transform(src, filename)
if err != nil {
return nil, code, err
Expand All @@ -101,7 +90,7 @@ type babel struct {
vm *goja.Runtime
this goja.Value
transform goja.Callable
mutex sync.Mutex //TODO: cache goja.CompileAST() in an init() function?
mutex sync.Mutex // TODO: cache goja.CompileAST() in an init() function?
}

func newBabel() (*babel, error) {
Expand Down
13 changes: 7 additions & 6 deletions js/compiler/compiler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"testing"

"github.com/dop251/goja"
"github.com/loadimpact/k6/lib"
"github.com/stretchr/testify/assert"
)

Expand Down Expand Up @@ -71,7 +72,7 @@ func TestCompile(t *testing.T) {
c := New()
t.Run("ES5", func(t *testing.T) {
src := `1+(function() { return 2; })()`
pgm, code, err := c.Compile(src, "script.js", "", "", true, CompatibilityModeBase)
pgm, code, err := c.Compile(src, "script.js", "", "", true, lib.CompatibilityModeBase)
if !assert.NoError(t, err) {
return
}
Expand All @@ -83,7 +84,7 @@ func TestCompile(t *testing.T) {

t.Run("Wrap", func(t *testing.T) {
pgm, code, err := c.Compile(src, "script.js",
"(function(){return ", "})", true, CompatibilityModeBase)
"(function(){return ", "})", true, lib.CompatibilityModeBase)
if !assert.NoError(t, err) {
return
}
Expand All @@ -102,14 +103,14 @@ func TestCompile(t *testing.T) {

t.Run("Invalid", func(t *testing.T) {
src := `1+(function() { return 2; )()`
_, _, err := c.Compile(src, "script.js", "", "", true, CompatibilityModeExtended)
_, _, err := c.Compile(src, "script.js", "", "", true, lib.CompatibilityModeExtended)
assert.IsType(t, &goja.Exception{}, err)
assert.Contains(t, err.Error(), `SyntaxError: script.js: Unexpected token (1:26)
> 1 | 1+(function() { return 2; )()`)
})
})
t.Run("ES6", func(t *testing.T) {
pgm, code, err := c.Compile(`1+(()=>2)()`, "script.js", "", "", true, CompatibilityModeExtended)
pgm, code, err := c.Compile(`1+(()=>2)()`, "script.js", "", "", true, lib.CompatibilityModeExtended)
if !assert.NoError(t, err) {
return
}
Expand All @@ -120,7 +121,7 @@ func TestCompile(t *testing.T) {
}

t.Run("Wrap", func(t *testing.T) {
pgm, code, err := c.Compile(`fn(1+(()=>2)())`, "script.js", "(function(fn){", "})", true, CompatibilityModeExtended)
pgm, code, err := c.Compile(`fn(1+(()=>2)())`, "script.js", "(function(fn){", "})", true, lib.CompatibilityModeExtended)
if !assert.NoError(t, err) {
return
}
Expand All @@ -141,7 +142,7 @@ func TestCompile(t *testing.T) {
})

t.Run("Invalid", func(t *testing.T) {
_, _, err := c.Compile(`1+(=>2)()`, "script.js", "", "", true, CompatibilityModeExtended)
_, _, err := c.Compile(`1+(=>2)()`, "script.js", "", "", true, lib.CompatibilityModeExtended)
assert.IsType(t, &goja.Exception{}, err)
assert.Contains(t, err.Error(), `SyntaxError: script.js: Unexpected token (1:3)
> 1 | 1+(=>2)()`)
Expand Down
7 changes: 4 additions & 3 deletions js/initcontext.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/loadimpact/k6/js/common"
"github.com/loadimpact/k6/js/compiler"
"github.com/loadimpact/k6/js/modules"
"github.com/loadimpact/k6/lib"
"github.com/loadimpact/k6/loader"
"github.com/pkg/errors"
"github.com/spf13/afero"
Expand Down Expand Up @@ -58,12 +59,12 @@ type InitContext struct {
// Cache of loaded programs and files.
programs map[string]programWithSource

compatibilityMode compiler.CompatibilityMode
compatibilityMode lib.CompatibilityMode
}

// NewInitContext creates a new initcontext with the provided arguments
func NewInitContext(
rt *goja.Runtime, c *compiler.Compiler, compatMode compiler.CompatibilityMode,
rt *goja.Runtime, c *compiler.Compiler, compatMode lib.CompatibilityMode,
ctxPtr *context.Context, filesystems map[string]afero.Fs, pwd *url.URL,
) *InitContext {
return &InitContext{
Expand All @@ -81,7 +82,7 @@ func newBoundInitContext(base *InitContext, ctxPtr *context.Context, rt *goja.Ru
// we don't copy the exports as otherwise they will be shared and we don't want this.
// this means that all the files will be executed again but once again only once per compilation
// of the main file.
var programs = make(map[string]programWithSource, len(base.programs))
programs := make(map[string]programWithSource, len(base.programs))
for key, program := range base.programs {
programs[key] = programWithSource{
src: program.src,
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 5047368

Please sign in to comment.