Skip to content

Commit

Permalink
Merge pull request #1206 from loadimpact/feat/1049-js-compatibility-m…
Browse files Browse the repository at this point in the history
…ode-option

Add JS compatibility mode option
  • Loading branch information
Ivan Mirić authored Nov 13, 2019
2 parents e24d8f9 + 3cd1799 commit 91a6828
Show file tree
Hide file tree
Showing 11 changed files with 447 additions and 218 deletions.
14 changes: 14 additions & 0 deletions cmd/runtime_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/loadimpact/k6/lib"
"github.com/pkg/errors"
"github.com/spf13/pflag"
"gopkg.in/guregu/null.v3"
)

var userEnvVarName = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_]*$`)
Expand All @@ -52,13 +53,20 @@ func runtimeOptionFlagSet(includeSysEnv bool) *pflag.FlagSet {
flags := pflag.NewFlagSet("", 0)
flags.SortFlags = false
flags.Bool("include-system-env-vars", includeSysEnv, "pass the real system environment variables to the runtime")
flags.String("compatibility-mode", "extended",
`JavaScript compiler compatibility mode, "extended" or "base"
base: pure Golang JS VM supporting ES5.1+
extended: base + Babel with ES2015 preset + core.js v2,
slower and memory consuming but with greater JS support
`)
flags.StringArrayP("env", "e", nil, "add/override environment variable with `VAR=value`")
return flags
}

func getRuntimeOptions(flags *pflag.FlagSet) (lib.RuntimeOptions, error) {
opts := lib.RuntimeOptions{
IncludeSystemEnvVars: getNullBool(flags, "include-system-env-vars"),
CompatibilityMode: getNullString(flags, "compatibility-mode"),
Env: make(map[string]string),
}

Expand All @@ -82,5 +90,11 @@ func getRuntimeOptions(flags *pflag.FlagSet) (lib.RuntimeOptions, error) {
opts.Env[k] = v
}

// Fallback to env
compatMode := opts.Env["K6_COMPATIBILITY_MODE"]
if !opts.CompatibilityMode.Valid && compatMode != "" {
opts.CompatibilityMode = null.StringFrom(compatMode)
}

return opts, nil
}
74 changes: 42 additions & 32 deletions js/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ type Bundle struct {

BaseInitContext *InitContext

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

// A BundleInstance is a self-contained instance of a Bundle.
Expand All @@ -60,25 +61,28 @@ type BundleInstance struct {

// NewBundle creates a new bundle from a source file and a filesystem.
func NewBundle(src *loader.SourceData, filesystems map[string]afero.Fs, rtOpts lib.RuntimeOptions) (*Bundle, error) {
compiler, err := compiler.New()
compatMode, err := lib.ValidateCompatibilityMode(rtOpts.CompatibilityMode.String)
if err != nil {
return nil, err
}

// Compile sources, both ES5 and ES6 are supported.
code := string(src.Data)
pgm, _, err := compiler.Compile(code, src.URL.String(), "", "", true)
c := compiler.New()
pgm, _, err := c.Compile(code, src.URL.String(), "", "", true, compatMode)
if err != nil {
return nil, err
}
// Make a bundle, instantiate it into a throwaway VM to populate caches.
rt := goja.New()
bundle := Bundle{
Filename: src.URL,
Source: code,
Program: pgm,
BaseInitContext: NewInitContext(rt, compiler, new(context.Context), filesystems, loader.Dir(src.URL)),
Env: rtOpts.Env,
Filename: src.URL,
Source: code,
Program: pgm,
BaseInitContext: NewInitContext(rt, c, compatMode, new(context.Context),
filesystems, loader.Dir(src.URL)),
Env: rtOpts.Env,
CompatibilityMode: compatMode,
}
if err := bundle.instantiate(rt, bundle.BaseInitContext); err != nil {
return nil, err
Expand Down Expand Up @@ -129,21 +133,23 @@ func NewBundle(src *loader.SourceData, filesystems map[string]afero.Fs, rtOpts l

// NewBundleFromArchive creates a new bundle from an lib.Archive.
func NewBundleFromArchive(arc *lib.Archive, rtOpts lib.RuntimeOptions) (*Bundle, error) {
compiler, err := compiler.New()
if err != nil {
return nil, err
}

if arc.Type != "js" {
return nil, errors.Errorf("expected bundle type 'js', got '%s'", arc.Type)
}

pgm, _, err := compiler.Compile(string(arc.Data), arc.FilenameURL.String(), "", "", true)
compatMode, err := lib.ValidateCompatibilityMode(arc.CompatibilityMode)
if err != nil {
return nil, err
}

c := compiler.New()
pgm, _, err := c.Compile(string(arc.Data), arc.FilenameURL.String(), "", "", true, compatMode)
if err != nil {
return nil, err
}

initctx := NewInitContext(goja.New(), compiler, new(context.Context), arc.Filesystems, arc.PwdURL)
initctx := NewInitContext(goja.New(), c, compatMode,
new(context.Context), arc.Filesystems, arc.PwdURL)

env := arc.Env
if env == nil {
Expand All @@ -155,12 +161,13 @@ func NewBundleFromArchive(arc *lib.Archive, rtOpts lib.RuntimeOptions) (*Bundle,
}

bundle := &Bundle{
Filename: arc.FilenameURL,
Source: string(arc.Data),
Program: pgm,
Options: arc.Options,
BaseInitContext: initctx,
Env: env,
Filename: arc.FilenameURL,
Source: string(arc.Data),
Program: pgm,
Options: arc.Options,
BaseInitContext: initctx,
Env: env,
CompatibilityMode: compatMode,
}
if err := bundle.instantiate(bundle.BaseInitContext.runtime, bundle.BaseInitContext); err != nil {
return nil, err
Expand All @@ -170,15 +177,16 @@ func NewBundleFromArchive(arc *lib.Archive, rtOpts lib.RuntimeOptions) (*Bundle,

func (b *Bundle) makeArchive() *lib.Archive {
arc := &lib.Archive{
Type: "js",
Filesystems: b.BaseInitContext.filesystems,
Options: b.Options,
FilenameURL: b.Filename,
Data: []byte(b.Source),
PwdURL: b.BaseInitContext.pwd,
Env: make(map[string]string, len(b.Env)),
K6Version: consts.Version,
Goos: runtime.GOOS,
Type: "js",
Filesystems: b.BaseInitContext.filesystems,
Options: b.Options,
FilenameURL: b.Filename,
Data: []byte(b.Source),
PwdURL: b.BaseInitContext.pwd,
Env: make(map[string]string, len(b.Env)),
CompatibilityMode: b.CompatibilityMode.String(),
K6Version: consts.Version,
Goos: runtime.GOOS,
}
// Copy env so changes in the archive are not reflected in the source Bundle
for k, v := range b.Env {
Expand Down Expand Up @@ -235,8 +243,10 @@ func (b *Bundle) instantiate(rt *goja.Runtime, init *InitContext) error {
rt.SetFieldNameMapper(common.FieldNameMapper{})
rt.SetRandSource(common.NewRandSource())

if _, err := rt.RunProgram(jslib.GetCoreJS()); err != nil {
return err
if init.compatibilityMode == compiler.CompatibilityModeExtended {
if _, err := rt.RunProgram(jslib.GetCoreJS()); err != nil {
return err
}
}

exports := rt.NewObject()
Expand Down
Loading

0 comments on commit 91a6828

Please sign in to comment.