Skip to content

Commit

Permalink
fix(js): properly handle missing compatibilityMode in archive
Browse files Browse the repository at this point in the history
This ensures old archives that don't contain the "compatibilityMode" key
in metadata.json will run with assumed "extended" JS compatibility.
  • Loading branch information
Ivan Mirić committed Nov 11, 2019
1 parent 6031817 commit 6953436
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 41 deletions.
17 changes: 6 additions & 11 deletions js/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,15 +133,15 @@ 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) {
compatMode, err := lib.ValidateCompatibilityMode(rtOpts.CompatibilityMode.String)
if err != nil {
return nil, err
}

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

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 {
Expand All @@ -160,19 +160,14 @@ func NewBundleFromArchive(arc *lib.Archive, rtOpts lib.RuntimeOptions) (*Bundle,
env[k] = v
}

cm, err := compiler.CompatibilityModeString(arc.CompatibilityMode)
if err != nil {
return nil, err
}

bundle := &Bundle{
Filename: arc.FilenameURL,
Source: string(arc.Data),
Program: pgm,
Options: arc.Options,
BaseInitContext: initctx,
Env: env,
CompatibilityMode: cm,
CompatibilityMode: compatMode,
}
if err := bundle.instantiate(bundle.BaseInitContext.runtime, bundle.BaseInitContext); err != nil {
return nil, err
Expand Down
94 changes: 64 additions & 30 deletions js/bundle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -426,42 +426,76 @@ func TestNewBundleFromArchive(t *testing.T) {
}
return b.makeArchive(), nil
}
testCases := []struct {
cm compiler.CompatibilityMode
code string
}{
{compiler.CompatibilityModeExtended, `

t.Run("ok", func(t *testing.T) {
testCases := []struct {
compatMode, code string
}{
// An empty value will assume "extended"
{"", `
export let options = { vus: 12345 };
export default function() { return "hi!"; };`},
{compiler.CompatibilityModeBase, `
{compiler.CompatibilityModeExtended.String(), `
export let options = { vus: 12345 };
export default function() { return "hi!"; };`},
{compiler.CompatibilityModeBase.String(), `
module.exports.options = { vus: 12345 };
module.exports.default = function() { return "hi!" };`},
}
}

for _, tc := range testCases {
tc := tc
t.Run(tc.cm.String(), func(t *testing.T) {
rtOpts := lib.RuntimeOptions{CompatibilityMode: null.StringFrom(tc.cm.String())}
arc, err := getArchive(tc.code, rtOpts)
assert.NoError(t, err)
b, err := NewBundleFromArchive(arc, rtOpts)
if !assert.NoError(t, err) {
return
}
assert.Equal(t, lib.Options{VUs: null.IntFrom(12345)}, b.Options)
assert.Equal(t, tc.cm, b.CompatibilityMode)
for _, tc := range testCases {
tc := tc
t.Run(tc.compatMode, func(t *testing.T) {
rtOpts := lib.RuntimeOptions{CompatibilityMode: null.StringFrom(tc.compatMode)}
arc, err := getArchive(tc.code, rtOpts)
assert.NoError(t, err)
b, err := NewBundleFromArchive(arc, rtOpts)
if !assert.NoError(t, err) {
return
}
assert.Equal(t, lib.Options{VUs: null.IntFrom(12345)}, b.Options)
expCM := tc.compatMode
if expCM == "" {
expCM = compiler.CompatibilityModeExtended.String()
}
assert.Equal(t, expCM, b.CompatibilityMode.String())

bi, err := b.Instantiate()
if !assert.NoError(t, err) {
return
}
val, err := bi.Default(goja.Undefined())
if !assert.NoError(t, err) {
return
}
assert.Equal(t, "hi!", val.Export())
})
}
bi, err := b.Instantiate()
if !assert.NoError(t, err) {
return
}
val, err := bi.Default(goja.Undefined())
if !assert.NoError(t, err) {
return
}
assert.Equal(t, "hi!", val.Export())
})
}
})
t.Run("err", func(t *testing.T) {
testCases := []struct {
compatMode, code, expErr string
}{
// Incompatible mode
{compiler.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", `
export let options = { vus: 12345 };
export default function() { return "hi!"; };`,
`invalid compatibility mode "wrongcompat". Use: "extended", "base"`},
}

for _, tc := range testCases {
tc := tc
t.Run(tc.compatMode, func(t *testing.T) {
rtOpts := lib.RuntimeOptions{CompatibilityMode: null.StringFrom(tc.compatMode)}
_, err := getArchive(tc.code, rtOpts)
assert.EqualError(t, err, tc.expErr)
})
}
})
}

func TestOpen(t *testing.T) {
Expand Down

0 comments on commit 6953436

Please sign in to comment.