Changes RuntimeConfig to an interface and exposes WithWasmCore2 (#518)

WebAssembly Core Working Draft 1 recently came out. Before that, we had
a toe-hold feature bucked called FinishedFeatures. This replaces
`RuntimeConfig.WithFinishedFeatures` with `RuntimeConfig.WithWasmCore2`.
This also adds `WithWasmCore1` for those who want to lock into 1.0
features as opposed to relying on defaults.

This also fixes some design debt where we hadn't finished migrating
public types that require constructor functions (NewXxx) to interfaces.
By using interfaces, we prevent people from accidentally initializing
key configuration directly (via &Xxx), causing nil field refs. This also
helps prevent confusion about how to use the type (ex pointer or not) as
there's only one way (as an interface).

See https://github.com/tetratelabs/wazero/issues/516

Signed-off-by: Adrian Cole <adrian@tetrate.io>
This commit is contained in:
Crypt Keeper
2022-05-02 10:29:38 +08:00
committed by GitHub
parent abd1c79f33
commit a91140f7f7
28 changed files with 293 additions and 199 deletions

View File

@@ -203,8 +203,13 @@ as well as how to classify a request for a feature we don't yet support.
### WebAssembly Core
wazero conforms with spectests [7] defined alongside WebAssembly Core
Specification [1.0][1]. There is also [work in progress][14] towards release
[2.0][2], despite it not being a Web Standard, yet.
Specification [1.0][1]. This is the default [RuntimeConfig][18].
The WebAssembly Core Specification [2.0][2] is in draft form and wazero has
[work in progress][14] towards that. Opt in via the below configuration:
```go
rConfig = wazero.NewRuntimeConfig().WithWasmCore2()
```
One current limitation of wazero is that it doesn't fully implement the Text
Format, yet, e.g. compiling `.wat` files. The intent is to [finish this][15],

View File

@@ -362,12 +362,12 @@ func TestNewModuleBuilder_Build(t *testing.T) {
func TestNewModuleBuilder_Build_Errors(t *testing.T) {
tests := []struct {
name string
input func(*RuntimeConfig) ModuleBuilder
input func(RuntimeConfig) ModuleBuilder
expectedErr string
}{
{
name: "memory min > limit", // only one test to avoid duplicating tests in module_test.go
input: func(cfg *RuntimeConfig) ModuleBuilder {
input: func(cfg RuntimeConfig) ModuleBuilder {
return NewRuntimeWithConfig(cfg).NewModuleBuilder("").
ExportMemory("memory", math.MaxUint32)
},
@@ -375,7 +375,7 @@ func TestNewModuleBuilder_Build_Errors(t *testing.T) {
},
{
name: "memory cap < min", // only one test to avoid duplicating tests in module_test.go
input: func(cfg *RuntimeConfig) ModuleBuilder {
input: func(cfg RuntimeConfig) ModuleBuilder {
cfg = cfg.WithMemoryCapacityPages(func(minPages uint32, maxPages *uint32) uint32 {
return 1
})

273
config.go
View File

@@ -16,8 +16,122 @@ import (
// RuntimeConfig controls runtime behavior, with the default implementation as NewRuntimeConfig
//
// Ex. To explicitly limit to Wasm Core 1.0 features as opposed to relying on defaults:
// rConfig = wazero.NewRuntimeConfig().WithWasmCore1()
//
// Note: RuntimeConfig is immutable. Each WithXXX function returns a new instance including the corresponding change.
type RuntimeConfig struct {
type RuntimeConfig interface {
// WithFeatureBulkMemoryOperations adds instructions modify ranges of memory or table entries
// ("bulk-memory-operations"). This defaults to false as the feature was not finished in WebAssembly 1.0 (20191205).
//
// Here are the notable effects:
// * Adds `memory.fill`, `memory.init`, `memory.copy` and `data.drop` instructions.
// * Adds `table.fill`, `table.init`, `table.copy` and `elem.drop` instructions.
// * Introduces a "passive" form of element and data segments.
// * Stops checking "active" element and data segment boundaries at compile-time, meaning they can error at runtime.
//
// Note: "bulk-memory-operations" is mixed with the "reference-types" proposal
// due to the WebAssembly Working Group merging them "mutually dependent".
// See https://github.com/WebAssembly/spec/blob/main/proposals/bulk-memory-operations/Overview.md
// See https://github.com/WebAssembly/spec/blob/main/proposals/reference-types/Overview.md
// See https://github.com/WebAssembly/spec/pull/1287
WithFeatureBulkMemoryOperations(enabled bool) RuntimeConfig
// WithFeatureMultiValue enables multiple values ("multi-value"). This defaults to false as the feature was not finished
// in WebAssembly 1.0 (20191205).
//
// Here are the notable effects:
// * Function (`func`) types allow more than one result
// * Block types (`block`, `loop` and `if`) can be arbitrary function types
//
// See https://github.com/WebAssembly/spec/blob/main/proposals/multi-value/Overview.md
WithFeatureMultiValue(enabled bool) RuntimeConfig
// WithFeatureMutableGlobal allows globals to be mutable. This defaults to true as the feature was finished in
// WebAssembly 1.0 (20191205).
//
// When false, an api.Global can never be cast to an api.MutableGlobal, and any source that includes global vars
// will fail to parse.
WithFeatureMutableGlobal(enabled bool) RuntimeConfig
// WithFeatureNonTrappingFloatToIntConversion enables non-trapping float-to-int conversions.
// ("nontrapping-float-to-int-conversion"). This defaults to false as the feature was not in WebAssembly 1.0 (20191205).
//
// The only effect of enabling this is allowing the following instructions, which return 0 on NaN instead of panicking.
// * `i32.trunc_sat_f32_s`
// * `i32.trunc_sat_f32_u`
// * `i32.trunc_sat_f64_s`
// * `i32.trunc_sat_f64_u`
// * `i64.trunc_sat_f32_s`
// * `i64.trunc_sat_f32_u`
// * `i64.trunc_sat_f64_s`
// * `i64.trunc_sat_f64_u`
//
// See https://github.com/WebAssembly/spec/blob/main/proposals/nontrapping-float-to-int-conversion/Overview.md
WithFeatureNonTrappingFloatToIntConversion(enabled bool) RuntimeConfig
// WithFeatureSignExtensionOps enables sign extension instructions ("sign-extension-ops"). This defaults to false as the
// feature was not in WebAssembly 1.0 (20191205).
//
// Here are the notable effects:
// * Adds instructions `i32.extend8_s`, `i32.extend16_s`, `i64.extend8_s`, `i64.extend16_s` and `i64.extend32_s`
//
// See https://github.com/WebAssembly/spec/blob/main/proposals/sign-extension-ops/Overview.md
WithFeatureSignExtensionOps(enabled bool) RuntimeConfig
// WithMemoryCapacityPages is a function that determines memory capacity in pages (65536 bytes per page). The inputs are
// the min and possibly nil max defined by the module, and the default is to return the min.
//
// Ex. To set capacity to max when exists:
// c = c.WithMemoryCapacityPages(func(minPages uint32, maxPages *uint32) uint32 {
// if maxPages != nil {
// return *maxPages
// }
// return minPages
// })
//
// This function is used at compile time (ModuleBuilder.Build or Runtime.CompileModule). Compile will err if the
// function returns a value lower than minPages or greater than WithMemoryLimitPages.
WithMemoryCapacityPages(maxCapacityPages func(minPages uint32, maxPages *uint32) uint32) RuntimeConfig
// WithMemoryLimitPages limits the maximum number of pages a module can define from 65536 pages (4GiB) to a lower value.
//
// Notes:
// * If a module defines no memory max value, Runtime.CompileModule sets max to the limit.
// * If a module defines a memory max larger than this limit, it will fail to compile (Runtime.CompileModule).
// * Any "memory.grow" instruction that results in a larger value than this results in an error at runtime.
// * Zero is a valid value and results in a crash if any module uses memory.
//
// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#grow-mem
// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#memory-types%E2%91%A0
WithMemoryLimitPages(memoryLimitPages uint32) RuntimeConfig
// WithWasmCore1 enables features included in the WebAssembly Core Specification 1.0 (20191205). Selecting this
// overwrites any currently accumulated features with only those included in this W3C recommendation.
//
// This is default because as of mid 2022, this is the only version that is a Web Standard (W3C Recommendation).
//
// You can select the latest draft of the WebAssembly Core Specification 2.0 instead via WithWasmCore2. You can
// also enable or disable individual features via `WithXXX` methods. Ex.
// rConfig = wazero.NewRuntimeConfig().WithWasmCore1().WithFeatureMutableGlobal(false)
//
// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/
WithWasmCore1() RuntimeConfig
// WithWasmCore2 enables features included in the WebAssembly Core Specification 2.0 (20220419). Selecting this
// overwrites any currently accumulated features with only those included in this W3C working draft.
//
// This is not default because it is not yet incomplete and also not yet a Web Standard (W3C Recommendation).
//
// Even after selecting this, you can enable or disable individual features via `WithXXX` methods. Ex.
// rConfig = wazero.NewRuntimeConfig().WithWasmCore2().WithFeatureMutableGlobal(false)
//
// See https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/
WithWasmCore2() RuntimeConfig
}
type runtimeConfig struct {
enabledFeatures wasm.Features
newEngine func(wasm.Features) wasm.Engine
memoryLimitPages uint32
@@ -25,15 +139,15 @@ type RuntimeConfig struct {
}
// engineLessConfig helps avoid copy/pasting the wrong defaults.
var engineLessConfig = &RuntimeConfig{
var engineLessConfig = &runtimeConfig{
enabledFeatures: wasm.Features20191205,
memoryLimitPages: wasm.MemoryLimitPages,
memoryCapacityPages: func(minPages uint32, maxPages *uint32) uint32 { return minPages },
}
// clone ensures all fields are copied even if nil.
func (c *RuntimeConfig) clone() *RuntimeConfig {
return &RuntimeConfig{
func (c *runtimeConfig) clone() *runtimeConfig {
return &runtimeConfig{
enabledFeatures: c.enabledFeatures,
newEngine: c.newEngine,
memoryLimitPages: c.memoryLimitPages,
@@ -45,49 +159,56 @@ func (c *RuntimeConfig) clone() *RuntimeConfig {
//
// Note: This panics at runtime the runtime.GOOS or runtime.GOARCH does not support JIT. Use NewRuntimeConfig to safely
// detect and fallback to NewRuntimeConfigInterpreter if needed.
func NewRuntimeConfigJIT() *RuntimeConfig {
func NewRuntimeConfigJIT() RuntimeConfig {
ret := engineLessConfig.clone()
ret.newEngine = jit.NewEngine
return ret
}
// NewRuntimeConfigInterpreter interprets WebAssembly modules instead of compiling them into assembly.
func NewRuntimeConfigInterpreter() *RuntimeConfig {
func NewRuntimeConfigInterpreter() RuntimeConfig {
ret := engineLessConfig.clone()
ret.newEngine = interpreter.NewEngine
return ret
}
// WithMemoryLimitPages limits the maximum number of pages a module can define from 65536 pages (4GiB) to a lower value.
//
// Notes:
// * If a module defines no memory max value, Runtime.CompileModule sets max to the limit.
// * If a module defines a memory max larger than this limit, it will fail to compile (Runtime.CompileModule).
// * Any "memory.grow" instruction that results in a larger value than this results in an error at runtime.
// * Zero is a valid value and results in a crash if any module uses memory.
//
// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#grow-mem
// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#memory-types%E2%91%A0
func (c *RuntimeConfig) WithMemoryLimitPages(memoryLimitPages uint32) *RuntimeConfig {
// WithFeatureBulkMemoryOperations implements RuntimeConfig.WithFeatureBulkMemoryOperations
func (c *runtimeConfig) WithFeatureBulkMemoryOperations(enabled bool) RuntimeConfig {
ret := c.clone()
ret.memoryLimitPages = memoryLimitPages
ret.enabledFeatures = ret.enabledFeatures.Set(wasm.FeatureBulkMemoryOperations, enabled)
return ret
}
// WithMemoryCapacityPages is a function that determines memory capacity in pages (65536 bytes per page). The inputs are
// the min and possibly nil max defined by the module, and the default is to return the min.
//
// Ex. To set capacity to max when exists:
// c = c.WithMemoryCapacityPages(func(minPages uint32, maxPages *uint32) uint32 {
// if maxPages != nil {
// return *maxPages
// }
// return minPages
// })
//
// This function is used at compile time (ModuleBuilder.Build or Runtime.CompileModule). Compile will err if the
// function returns a value lower than minPages or greater than WithMemoryLimitPages.
func (c *RuntimeConfig) WithMemoryCapacityPages(maxCapacityPages func(minPages uint32, maxPages *uint32) uint32) *RuntimeConfig {
// WithFeatureMultiValue implements RuntimeConfig.WithFeatureMultiValue
func (c *runtimeConfig) WithFeatureMultiValue(enabled bool) RuntimeConfig {
ret := c.clone()
ret.enabledFeatures = ret.enabledFeatures.Set(wasm.FeatureMultiValue, enabled)
return ret
}
// WithFeatureMutableGlobal implements RuntimeConfig.WithFeatureMutableGlobal
func (c *runtimeConfig) WithFeatureMutableGlobal(enabled bool) RuntimeConfig {
ret := c.clone()
ret.enabledFeatures = ret.enabledFeatures.Set(wasm.FeatureMutableGlobal, enabled)
return ret
}
// WithFeatureNonTrappingFloatToIntConversion implements RuntimeConfig.WithFeatureNonTrappingFloatToIntConversion
func (c *runtimeConfig) WithFeatureNonTrappingFloatToIntConversion(enabled bool) RuntimeConfig {
ret := c.clone()
ret.enabledFeatures = ret.enabledFeatures.Set(wasm.FeatureNonTrappingFloatToIntConversion, enabled)
return ret
}
// WithFeatureSignExtensionOps implements RuntimeConfig.WithFeatureSignExtensionOps
func (c *runtimeConfig) WithFeatureSignExtensionOps(enabled bool) RuntimeConfig {
ret := c.clone()
ret.enabledFeatures = ret.enabledFeatures.Set(wasm.FeatureSignExtensionOps, enabled)
return ret
}
// WithMemoryCapacityPages implements RuntimeConfig.WithMemoryCapacityPages
func (c *runtimeConfig) WithMemoryCapacityPages(maxCapacityPages func(minPages uint32, maxPages *uint32) uint32) RuntimeConfig {
if maxCapacityPages == nil {
return c // Instead of erring.
}
@@ -96,94 +217,24 @@ func (c *RuntimeConfig) WithMemoryCapacityPages(maxCapacityPages func(minPages u
return ret
}
// WithFinishedFeatures enables currently supported "finished" feature proposals. Use this to improve compatibility with
// tools that enable all features by default.
//
// Note: The features implied can vary and can lead to unpredictable behavior during updates.
// Note: This only includes "finished" features, but "finished" is not an official W3C term: it is possible that
// "finished" features do not make the next W3C recommended WebAssembly core specification.
// See https://github.com/WebAssembly/spec/tree/main/proposals
func (c *RuntimeConfig) WithFinishedFeatures() *RuntimeConfig {
// WithMemoryLimitPages implements RuntimeConfig.WithMemoryLimitPages
func (c *runtimeConfig) WithMemoryLimitPages(memoryLimitPages uint32) RuntimeConfig {
ret := c.clone()
ret.enabledFeatures = wasm.FeaturesFinished
ret.memoryLimitPages = memoryLimitPages
return ret
}
// WithFeatureBulkMemoryOperations adds instructions modify ranges of memory or table entries
// ("bulk-memory-operations"). This defaults to false as the feature was not finished in WebAssembly 1.0 (20191205).
//
// Here are the notable effects:
// * Adds `memory.fill`, `memory.init`, `memory.copy` and `data.drop` instructions.
// * Adds `table.fill`, `table.init`, `table.copy` and `elem.drop` instructions.
// * Introduces a "passive" form of element and data segments.
// * Stops checking "active" element and data segment boundaries at compile-time, meaning they can error at runtime.
//
// Note: "bulk-memory-operations" is mixed with the "reference-types" proposal
// due to the WebAssembly Working Group merging them "mutually dependent".
// See https://github.com/WebAssembly/spec/blob/main/proposals/bulk-memory-operations/Overview.md
// See https://github.com/WebAssembly/spec/blob/main/proposals/reference-types/Overview.md
// See https://github.com/WebAssembly/spec/pull/1287
func (c *RuntimeConfig) WithFeatureBulkMemoryOperations(enabled bool) *RuntimeConfig {
// WithWasmCore1 implements RuntimeConfig.WithWasmCore1
func (c *runtimeConfig) WithWasmCore1() RuntimeConfig {
ret := c.clone()
ret.enabledFeatures = ret.enabledFeatures.Set(wasm.FeatureBulkMemoryOperations, enabled)
ret.enabledFeatures = wasm.Features20191205
return ret
}
// WithFeatureMultiValue enables multiple values ("multi-value"). This defaults to false as the feature was not finished
// in WebAssembly 1.0 (20191205).
//
// Here are the notable effects:
// * Function (`func`) types allow more than one result
// * Block types (`block`, `loop` and `if`) can be arbitrary function types
//
// See https://github.com/WebAssembly/spec/blob/main/proposals/multi-value/Overview.md
func (c *RuntimeConfig) WithFeatureMultiValue(enabled bool) *RuntimeConfig {
// WithWasmCore2 implements RuntimeConfig.WithWasmCore2
func (c *runtimeConfig) WithWasmCore2() RuntimeConfig {
ret := c.clone()
ret.enabledFeatures = ret.enabledFeatures.Set(wasm.FeatureMultiValue, enabled)
return ret
}
// WithFeatureMutableGlobal allows globals to be mutable. This defaults to true as the feature was finished in
// WebAssembly 1.0 (20191205).
//
// When false, an api.Global can never be cast to an api.MutableGlobal, and any source that includes global vars
// will fail to parse.
func (c *RuntimeConfig) WithFeatureMutableGlobal(enabled bool) *RuntimeConfig {
ret := c.clone()
ret.enabledFeatures = ret.enabledFeatures.Set(wasm.FeatureMutableGlobal, enabled)
return ret
}
// WithFeatureNonTrappingFloatToIntConversion enables non-trapping float-to-int conversions.
// ("nontrapping-float-to-int-conversion"). This defaults to false as the feature was not in WebAssembly 1.0 (20191205).
//
// The only effect of enabling this is allowing the following instructions, which return 0 on NaN instead of panicking.
// * `i32.trunc_sat_f32_s`
// * `i32.trunc_sat_f32_u`
// * `i32.trunc_sat_f64_s`
// * `i32.trunc_sat_f64_u`
// * `i64.trunc_sat_f32_s`
// * `i64.trunc_sat_f32_u`
// * `i64.trunc_sat_f64_s`
// * `i64.trunc_sat_f64_u`
//
// See https://github.com/WebAssembly/spec/blob/main/proposals/nontrapping-float-to-int-conversion/Overview.md
func (c *RuntimeConfig) WithFeatureNonTrappingFloatToIntConversion(enabled bool) *RuntimeConfig {
ret := c.clone()
ret.enabledFeatures = ret.enabledFeatures.Set(wasm.FeatureNonTrappingFloatToIntConversion, enabled)
return ret
}
// WithFeatureSignExtensionOps enables sign extension instructions ("sign-extension-ops"). This defaults to false as the
// feature was not in WebAssembly 1.0 (20191205).
//
// Here are the notable effects:
// * Adds instructions `i32.extend8_s`, `i32.extend16_s`, `i64.extend8_s`, `i64.extend16_s` and `i64.extend32_s`
//
// See https://github.com/WebAssembly/spec/blob/main/proposals/sign-extension-ops/Overview.md
func (c *RuntimeConfig) WithFeatureSignExtensionOps(enabled bool) *RuntimeConfig {
ret := c.clone()
ret.enabledFeatures = ret.enabledFeatures.Set(wasm.FeatureSignExtensionOps, enabled)
ret.enabledFeatures = wasm.Features20220419
return ret
}

View File

@@ -5,6 +5,6 @@ package wazero
const JITSupported = true
// NewRuntimeConfig returns NewRuntimeConfigJIT
func NewRuntimeConfig() *RuntimeConfig {
func NewRuntimeConfig() RuntimeConfig {
return NewRuntimeConfigJIT()
}

View File

@@ -14,90 +14,108 @@ import (
func TestRuntimeConfig(t *testing.T) {
tests := []struct {
name string
with func(*RuntimeConfig) *RuntimeConfig
expected *RuntimeConfig
with func(RuntimeConfig) RuntimeConfig
expected RuntimeConfig
}{
{
name: "WithMemoryLimitPages",
with: func(c *RuntimeConfig) *RuntimeConfig {
with: func(c RuntimeConfig) RuntimeConfig {
return c.WithMemoryLimitPages(1)
},
expected: &RuntimeConfig{
expected: &runtimeConfig{
memoryLimitPages: 1,
},
},
{
name: "bulk-memory-operations",
with: func(c *RuntimeConfig) *RuntimeConfig {
with: func(c RuntimeConfig) RuntimeConfig {
return c.WithFeatureBulkMemoryOperations(true)
},
expected: &RuntimeConfig{
expected: &runtimeConfig{
enabledFeatures: wasm.FeatureBulkMemoryOperations,
},
},
{
name: "multi-value",
with: func(c *RuntimeConfig) *RuntimeConfig {
with: func(c RuntimeConfig) RuntimeConfig {
return c.WithFeatureMultiValue(true)
},
expected: &RuntimeConfig{
expected: &runtimeConfig{
enabledFeatures: wasm.FeatureMultiValue,
},
},
{
name: "mutable-global",
with: func(c *RuntimeConfig) *RuntimeConfig {
with: func(c RuntimeConfig) RuntimeConfig {
return c.WithFeatureMutableGlobal(true)
},
expected: &RuntimeConfig{
expected: &runtimeConfig{
enabledFeatures: wasm.FeatureMutableGlobal,
},
},
{
name: "nontrapping-float-to-int-conversion",
with: func(c *RuntimeConfig) *RuntimeConfig {
with: func(c RuntimeConfig) RuntimeConfig {
return c.WithFeatureNonTrappingFloatToIntConversion(true)
},
expected: &RuntimeConfig{
expected: &runtimeConfig{
enabledFeatures: wasm.FeatureNonTrappingFloatToIntConversion,
},
},
{
name: "sign-extension-ops",
with: func(c *RuntimeConfig) *RuntimeConfig {
with: func(c RuntimeConfig) RuntimeConfig {
return c.WithFeatureSignExtensionOps(true)
},
expected: &RuntimeConfig{
expected: &runtimeConfig{
enabledFeatures: wasm.FeatureSignExtensionOps,
},
},
{
name: "REC-wasm-core-1-20191205",
with: func(c RuntimeConfig) RuntimeConfig {
return c.WithFeatureSignExtensionOps(true).WithWasmCore1()
},
expected: &runtimeConfig{
enabledFeatures: wasm.Features20191205,
},
},
{
name: "WD-wasm-core-2-20220419",
with: func(c RuntimeConfig) RuntimeConfig {
return c.WithFeatureMutableGlobal(false).WithWasmCore2()
},
expected: &runtimeConfig{
enabledFeatures: wasm.Features20220419,
},
},
}
for _, tt := range tests {
tc := tt
t.Run(tc.name, func(t *testing.T) {
input := &RuntimeConfig{}
input := &runtimeConfig{}
rc := tc.with(input)
require.Equal(t, tc.expected, rc)
// The source wasn't modified
require.Equal(t, &RuntimeConfig{}, input)
require.Equal(t, &runtimeConfig{}, input)
})
}
t.Run("WithMemoryCapacityPages", func(t *testing.T) {
c := NewRuntimeConfig()
c := NewRuntimeConfig().(*runtimeConfig)
// Test default returns min
require.Equal(t, uint32(1), c.memoryCapacityPages(1, nil))
// Nil ignored
c = c.WithMemoryCapacityPages(nil)
c = c.WithMemoryCapacityPages(nil).(*runtimeConfig)
require.Equal(t, uint32(1), c.memoryCapacityPages(1, nil))
// Assign a valid function
c = c.WithMemoryCapacityPages(func(minPages uint32, maxPages *uint32) uint32 {
return 2
})
}).(*runtimeConfig)
// Returns updated value
require.Equal(t, uint32(2), c.memoryCapacityPages(1, nil))
})
@@ -108,13 +126,13 @@ func TestRuntimeConfig_FeatureToggle(t *testing.T) {
name string
feature wasm.Features
expectDefault bool
setFeature func(*RuntimeConfig, bool) *RuntimeConfig
setFeature func(RuntimeConfig, bool) RuntimeConfig
}{
{
name: "bulk-memory-operations",
feature: wasm.FeatureBulkMemoryOperations,
expectDefault: false,
setFeature: func(c *RuntimeConfig, v bool) *RuntimeConfig {
setFeature: func(c RuntimeConfig, v bool) RuntimeConfig {
return c.WithFeatureBulkMemoryOperations(v)
},
},
@@ -122,7 +140,7 @@ func TestRuntimeConfig_FeatureToggle(t *testing.T) {
name: "multi-value",
feature: wasm.FeatureMultiValue,
expectDefault: false,
setFeature: func(c *RuntimeConfig, v bool) *RuntimeConfig {
setFeature: func(c RuntimeConfig, v bool) RuntimeConfig {
return c.WithFeatureMultiValue(v)
},
},
@@ -130,7 +148,7 @@ func TestRuntimeConfig_FeatureToggle(t *testing.T) {
name: "mutable-global",
feature: wasm.FeatureMutableGlobal,
expectDefault: true,
setFeature: func(c *RuntimeConfig, v bool) *RuntimeConfig {
setFeature: func(c RuntimeConfig, v bool) RuntimeConfig {
return c.WithFeatureMutableGlobal(v)
},
},
@@ -138,7 +156,7 @@ func TestRuntimeConfig_FeatureToggle(t *testing.T) {
name: "nontrapping-float-to-int-conversion",
feature: wasm.FeatureNonTrappingFloatToIntConversion,
expectDefault: false,
setFeature: func(c *RuntimeConfig, v bool) *RuntimeConfig {
setFeature: func(c RuntimeConfig, v bool) RuntimeConfig {
return c.WithFeatureNonTrappingFloatToIntConversion(v)
},
},
@@ -146,7 +164,7 @@ func TestRuntimeConfig_FeatureToggle(t *testing.T) {
name: "sign-extension-ops",
feature: wasm.FeatureSignExtensionOps,
expectDefault: false,
setFeature: func(c *RuntimeConfig, v bool) *RuntimeConfig {
setFeature: func(c RuntimeConfig, v bool) RuntimeConfig {
return c.WithFeatureSignExtensionOps(v)
},
},
@@ -156,19 +174,19 @@ func TestRuntimeConfig_FeatureToggle(t *testing.T) {
tc := tt
t.Run(tc.name, func(t *testing.T) {
c := NewRuntimeConfig()
c := NewRuntimeConfig().(*runtimeConfig)
require.Equal(t, tc.expectDefault, c.enabledFeatures.Get(tc.feature))
// Set to false even if it was initially false.
c = tc.setFeature(c, false)
c = tc.setFeature(c, false).(*runtimeConfig)
require.False(t, c.enabledFeatures.Get(tc.feature))
// Set true makes it true
c = tc.setFeature(c, true)
c = tc.setFeature(c, true).(*runtimeConfig)
require.True(t, c.enabledFeatures.Get(tc.feature))
// Set false makes it false again
c = tc.setFeature(c, false)
c = tc.setFeature(c, false).(*runtimeConfig)
require.False(t, c.enabledFeatures.Get(tc.feature))
})
}

View File

@@ -5,6 +5,6 @@ package wazero
const JITSupported = false
// NewRuntimeConfig returns NewRuntimeConfigInterpreter
func NewRuntimeConfig() *RuntimeConfig {
func NewRuntimeConfig() RuntimeConfig {
return NewRuntimeConfigInterpreter()
}

View File

@@ -48,7 +48,7 @@ func main() {
// wazero enables only W3C recommended features by default. Opt-in to other features like so:
runtimeWithMultiValue := wazero.NewRuntimeWithConfig(
wazero.NewRuntimeConfig().WithFeatureMultiValue(true),
// ^^ Note: You can enable all features via WithFinishedFeatures.
// ^^ Note: WebAssembly 2.0 (WithWasmCore2) includes "multi-value".
)
// Add a module that uses multiple results values, with functions defined in WebAssembly.

View File

@@ -153,8 +153,8 @@ func runRandomMatMul(b *testing.B, m api.Module) {
}
}
func instantiateHostFunctionModuleWithEngine(b *testing.B, engine *wazero.RuntimeConfig) api.Module {
r := createRuntime(b, engine)
func instantiateHostFunctionModuleWithEngine(b *testing.B, config wazero.RuntimeConfig) api.Module {
r := createRuntime(b, config)
// InstantiateModuleFromCode runs the "_start" function which is what TinyGo compiles "main" to.
m, err := r.InstantiateModuleFromCode(testCtx, caseWasm)
@@ -164,7 +164,7 @@ func instantiateHostFunctionModuleWithEngine(b *testing.B, engine *wazero.Runtim
return m
}
func createRuntime(b *testing.B, engine *wazero.RuntimeConfig) wazero.Runtime {
func createRuntime(b *testing.B, config wazero.RuntimeConfig) wazero.Runtime {
getRandomString := func(ctx context.Context, m api.Module, retBufPtr uint32, retBufSize uint32) {
results, err := m.ExportedFunction("allocate_buffer").Call(ctx, 10)
if err != nil {
@@ -179,7 +179,7 @@ func createRuntime(b *testing.B, engine *wazero.RuntimeConfig) wazero.Runtime {
m.Memory().Write(ctx, offset, b)
}
r := wazero.NewRuntimeWithConfig(engine)
r := wazero.NewRuntimeWithConfig(config)
_, err := r.NewModuleBuilder("env").
ExportFunction("get_random_string", getRandomString).

View File

@@ -42,7 +42,7 @@ func TestEngineInterpreter(t *testing.T) {
runAllTests(t, tests, wazero.NewRuntimeConfigInterpreter())
}
func runAllTests(t *testing.T, tests map[string]func(t *testing.T, r wazero.Runtime), config *wazero.RuntimeConfig) {
func runAllTests(t *testing.T, tests map[string]func(t *testing.T, r wazero.Runtime), config wazero.RuntimeConfig) {
for name, testf := range tests {
name := name // pin
testf := testf // pin

View File

@@ -45,7 +45,7 @@ var (
elemDropWasm []byte
)
func requireErrorOnBulkMemoryFeatureDisabled(t *testing.T, newRuntimeConfig func() *wazero.RuntimeConfig, bin []byte) {
func requireErrorOnBulkMemoryFeatureDisabled(t *testing.T, newRuntimeConfig func() wazero.RuntimeConfig, bin []byte) {
t.Run("disabled", func(t *testing.T) {
// bulk-memory-operations is disabled by default.
r := wazero.NewRuntimeWithConfig(newRuntimeConfig())
@@ -54,7 +54,7 @@ func requireErrorOnBulkMemoryFeatureDisabled(t *testing.T, newRuntimeConfig func
})
}
func testTableCopy(t *testing.T, newRuntimeConfig func() *wazero.RuntimeConfig) {
func testTableCopy(t *testing.T, newRuntimeConfig func() wazero.RuntimeConfig) {
t.Run("table.copy", func(t *testing.T) {
requireErrorOnBulkMemoryFeatureDisabled(t, newRuntimeConfig, tableCopyWasm)
@@ -123,7 +123,7 @@ func testTableCopy(t *testing.T, newRuntimeConfig func() *wazero.RuntimeConfig)
})
}
func testTableInit(t *testing.T, newRuntimeConfig func() *wazero.RuntimeConfig) {
func testTableInit(t *testing.T, newRuntimeConfig func() wazero.RuntimeConfig) {
t.Run("table.init", func(t *testing.T) {
requireErrorOnBulkMemoryFeatureDisabled(t, newRuntimeConfig, tableInitWasm)
@@ -166,7 +166,7 @@ func testTableInit(t *testing.T, newRuntimeConfig func() *wazero.RuntimeConfig)
})
}
func testElemDrop(t *testing.T, newRuntimeConfig func() *wazero.RuntimeConfig) {
func testElemDrop(t *testing.T, newRuntimeConfig func() wazero.RuntimeConfig) {
t.Run("elem.drop", func(t *testing.T) {
requireErrorOnBulkMemoryFeatureDisabled(t, newRuntimeConfig, elemDropWasm)
@@ -194,7 +194,7 @@ func testElemDrop(t *testing.T, newRuntimeConfig func() *wazero.RuntimeConfig) {
})
}
func testBulkMemoryOperations(t *testing.T, newRuntimeConfig func() *wazero.RuntimeConfig) {
func testBulkMemoryOperations(t *testing.T, newRuntimeConfig func() wazero.RuntimeConfig) {
requireErrorOnBulkMemoryFeatureDisabled(t, newRuntimeConfig, bulkMemoryOperationsWasm)
t.Run("enabled", func(t *testing.T) {

View File

@@ -28,7 +28,7 @@ func TestMultiValue_Interpreter(t *testing.T) {
//go:embed testdata/multi_value.wasm
var multiValueWasm []byte
func testMultiValue(t *testing.T, newRuntimeConfig func() *wazero.RuntimeConfig) {
func testMultiValue(t *testing.T, newRuntimeConfig func() wazero.RuntimeConfig) {
t.Run("disabled", func(t *testing.T) {
// multi-value is disabled by default.
r := wazero.NewRuntimeWithConfig(newRuntimeConfig())

View File

@@ -56,7 +56,7 @@ var nonTrappingFloatToIntConversion = []byte(`(module $conversions.wast
)
`)
func testNonTrappingFloatToIntConversion(t *testing.T, newRuntimeConfig func() *wazero.RuntimeConfig) {
func testNonTrappingFloatToIntConversion(t *testing.T, newRuntimeConfig func() wazero.RuntimeConfig) {
t.Run("disabled", func(t *testing.T) {
// Non-trapping Float-to-int Conversions are disabled by default.
r := wazero.NewRuntimeWithConfig(newRuntimeConfig())

View File

@@ -45,7 +45,7 @@ var signExtend = []byte(`(module
)
`)
func testSignExtensionOps(t *testing.T, newRuntimeConfig func() *wazero.RuntimeConfig) {
func testSignExtensionOps(t *testing.T, newRuntimeConfig func() wazero.RuntimeConfig) {
t.Run("disabled", func(t *testing.T) {
// Sign-extension is disabled by default.
r := wazero.NewRuntimeWithConfig(newRuntimeConfig())

View File

@@ -92,7 +92,7 @@ func newExample() *wasm.Module {
func BenchmarkWat2Wasm(b *testing.B, vsName string, vsWat2Wasm func([]byte) error) {
b.Run("wazero", func(b *testing.B) {
for i := 0; i < b.N; i++ {
if m, err := text.DecodeModule(exampleText, wasm.FeaturesFinished, wasm.MemoryLimitPages); err != nil {
if m, err := text.DecodeModule(exampleText, wasm.Features20220419, wasm.MemoryLimitPages); err != nil {
b.Fatal(err)
} else {
_ = binary.EncodeModule(m)

View File

@@ -14,19 +14,19 @@ import (
func TestExampleUpToDate(t *testing.T) {
t.Run("binary.DecodeModule", func(t *testing.T) {
m, err := binary.DecodeModule(exampleBinary, wasm.FeaturesFinished, wasm.MemoryLimitPages)
m, err := binary.DecodeModule(exampleBinary, wasm.Features20220419, wasm.MemoryLimitPages)
require.NoError(t, err)
require.Equal(t, example, m)
})
t.Run("text.DecodeModule", func(t *testing.T) {
m, err := text.DecodeModule(exampleText, wasm.FeaturesFinished, wasm.MemoryLimitPages)
m, err := text.DecodeModule(exampleText, wasm.Features20220419, wasm.MemoryLimitPages)
require.NoError(t, err)
require.Equal(t, example, m)
})
t.Run("Executable", func(t *testing.T) {
r := wazero.NewRuntimeWithConfig(wazero.NewRuntimeConfig().WithFinishedFeatures())
r := wazero.NewRuntimeWithConfig(wazero.NewRuntimeConfig().WithWasmCore2())
// Add WASI to satisfy import tests
wm, err := wasi.InstantiateSnapshotPreview1(testCtx, r)
@@ -49,7 +49,7 @@ func BenchmarkCodec(b *testing.B) {
b.Run("binary.DecodeModule", func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := binary.DecodeModule(exampleBinary, wasm.FeaturesFinished, wasm.MemoryLimitPages); err != nil {
if _, err := binary.DecodeModule(exampleBinary, wasm.Features20220419, wasm.MemoryLimitPages); err != nil {
b.Fatal(err)
}
}
@@ -63,7 +63,7 @@ func BenchmarkCodec(b *testing.B) {
b.Run("text.DecodeModule", func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := text.DecodeModule(exampleText, wasm.FeaturesFinished, wasm.MemoryLimitPages); err != nil {
if _, err := text.DecodeModule(exampleText, wasm.Features20220419, wasm.MemoryLimitPages); err != nil {
b.Fatal(err)
}
}

View File

@@ -38,20 +38,20 @@ type Module interface {
}
func NewWazeroInterpreterRuntime() Runtime {
return newWazeroRuntime("wazero-interpreter", wazero.NewRuntimeConfigInterpreter().WithFinishedFeatures())
return newWazeroRuntime("wazero-interpreter", wazero.NewRuntimeConfigInterpreter().WithWasmCore2())
}
func NewWazeroJITRuntime() Runtime {
return newWazeroRuntime(jitRuntime, wazero.NewRuntimeConfigJIT().WithFinishedFeatures())
return newWazeroRuntime(jitRuntime, wazero.NewRuntimeConfigJIT().WithWasmCore2())
}
func newWazeroRuntime(name string, config *wazero.RuntimeConfig) *wazeroRuntime {
func newWazeroRuntime(name string, config wazero.RuntimeConfig) *wazeroRuntime {
return &wazeroRuntime{name: name, config: config}
}
type wazeroRuntime struct {
name string
config *wazero.RuntimeConfig
config wazero.RuntimeConfig
runtime wazero.Runtime
logFn func([]byte) error
env, compiled *wazero.CompiledCode

View File

@@ -28,7 +28,7 @@ const (
func TestModGen(t *testing.T) {
tested := map[string]struct{}{}
rand := rand.New(rand.NewSource(0)) // use deterministic seed source for easy debugging.
runtime := wazero.NewRuntimeWithConfig(wazero.NewRuntimeConfig().WithFinishedFeatures())
runtime := wazero.NewRuntimeWithConfig(wazero.NewRuntimeConfig().WithWasmCore2())
for _, size := range []int{1, 2, 5, 10, 50, 100} {
for i := 0; i < 100; i++ {
seed := make([]byte, size)

View File

@@ -72,7 +72,7 @@ func TestFunctionType(t *testing.T) {
})
t.Run(fmt.Sprintf("decode - %s", tc.name), func(t *testing.T) {
binary, err := decodeFunctionType(wasm.FeaturesFinished, bytes.NewReader(b))
binary, err := decodeFunctionType(wasm.Features20220419, bytes.NewReader(b))
require.NoError(t, err)
require.Equal(t, binary, tc.input)
})

View File

@@ -12,14 +12,20 @@ type Features uint64
// Features20191205 include those finished in WebAssembly 1.0 (20191205).
//
// See https://github.com/WebAssembly/proposals/blob/main/finished-proposals.md
// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205
const Features20191205 = FeatureMutableGlobal
// FeaturesFinished include all supported finished features, regardless of W3C status.
// Features20220419 include those finished in WebAssembly 2.0 (20220419).
//
// See https://github.com/WebAssembly/proposals/blob/main/finished-proposals.md
const FeaturesFinished = 0xffffffffffffffff
// TODO: not yet complete https://github.com/tetratelabs/wazero/issues/484
// See https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/appendix/changes.html#release-1-1
const Features20220419 = Features20191205 |
FeatureBulkMemoryOperations |
FeatureMultiValue |
FeatureNonTrappingFloatToIntConversion |
// TODO: FeatureReferenceTypes |
FeatureSignExtensionOps
// TODO: FeatureSIMD
const (
// FeatureBulkMemoryOperations decides if parsing should succeed on the following instructions:

View File

@@ -62,7 +62,7 @@ func TestFeatures_String(t *testing.T) {
{name: "multi-value", feature: FeatureMultiValue, expected: "multi-value"},
{name: "features", feature: FeatureMutableGlobal | FeatureMultiValue, expected: "multi-value|mutable-global"},
{name: "undefined", feature: 1 << 63, expected: ""},
{name: "all", feature: FeaturesFinished, expected: "bulk-memory-operations|multi-value|mutable-global|nontrapping-float-to-int-conversion|sign-extension-ops"},
{name: "2.0", feature: Features20220419, expected: "bulk-memory-operations|multi-value|mutable-global|nontrapping-float-to-int-conversion|sign-extension-ops"},
}
for _, tt := range tests {

View File

@@ -247,7 +247,7 @@ func TestPopGoFuncParams(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
goFunc := reflect.ValueOf(tc.inputFunc)
fk, _, err := getFunctionType(&goFunc, FeaturesFinished)
fk, _, err := getFunctionType(&goFunc, Features20220419)
require.NoError(t, err)
vals := PopGoFuncParams(&FunctionInstance{Kind: fk, GoFunc: &goFunc}, (&stack{stackVals}).pop)
@@ -387,7 +387,7 @@ func TestCallGoFunc(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
goFunc := reflect.ValueOf(tc.inputFunc)
fk, _, err := getFunctionType(&goFunc, FeaturesFinished)
fk, _, err := getFunctionType(&goFunc, Features20220419)
require.NoError(t, err)
results := CallGoFunc(testCtx, callCtx, &FunctionInstance{Kind: fk, GoFunc: &goFunc}, tc.inputParams)

View File

@@ -1564,7 +1564,7 @@ func TestDecodeModule(t *testing.T) {
tc := tt
t.Run(tc.name, func(t *testing.T) {
m, err := DecodeModule([]byte(tc.input), wasm.FeaturesFinished, wasm.MemoryLimitPages)
m, err := DecodeModule([]byte(tc.input), wasm.Features20220419, wasm.MemoryLimitPages)
require.NoError(t, err)
require.Equal(t, tc.expected, m)
})

View File

@@ -272,7 +272,7 @@ func TestFuncParser(t *testing.T) {
}
module := &wasm.Module{}
fp := newFuncParser(wasm.FeaturesFinished, &typeUseParser{module: module}, newIndexNamespace(module.SectionElementCount), setFunc)
fp := newFuncParser(wasm.Features20220419, &typeUseParser{module: module}, newIndexNamespace(module.SectionElementCount), setFunc)
require.NoError(t, parseFunc(fp, tc.source))
require.Equal(t, tc.expected, parsedCode)
})
@@ -390,7 +390,7 @@ func TestFuncParser_Call_Resolved(t *testing.T) {
return parseErr, nil
}
fp := newFuncParser(wasm.FeaturesFinished, &typeUseParser{module: &wasm.Module{}}, funcNamespace, setFunc)
fp := newFuncParser(wasm.Features20220419, &typeUseParser{module: &wasm.Module{}}, funcNamespace, setFunc)
require.NoError(t, parseFunc(fp, tc.source))
require.Equal(t, tc.expected, parsedCode)
})

View File

@@ -189,7 +189,7 @@ func TestTypeParser(t *testing.T) {
require.Equal(t, wasm.SectionIDType, sectionID)
return 0
})
parsed, tp, err := parseFunctionType(wasm.FeaturesFinished, typeNamespace, tc.input)
parsed, tp, err := parseFunctionType(wasm.Features20220419, typeNamespace, tc.input)
require.NoError(t, err)
require.Equal(t, tc.expected, parsed)
require.Equal(t, uint32(1), tp.typeNamespace.count)
@@ -291,13 +291,13 @@ func TestTypeParser_Errors(t *testing.T) {
{
name: "result second wrong",
input: "(type (func (result i32) (result i33)))",
enabledFeatures: wasm.FeaturesFinished,
enabledFeatures: wasm.Features20220419,
expectedErr: "unknown type: i33",
},
{
name: "result second redundant type wrong",
input: "(type (func (result i32) (result i32 i33)))",
enabledFeatures: wasm.FeaturesFinished,
enabledFeatures: wasm.Features20220419,
expectedErr: "unknown type: i33",
},
{

View File

@@ -160,7 +160,7 @@ func TestTypeUseParser_InlinesTypesWhenNotYetAdded(t *testing.T) {
runTypeUseParserTests(t, tests, func(tc *typeUseParserTest) (*typeUseParser, func(t *testing.T)) {
module := &wasm.Module{}
tp := newTypeUseParser(wasm.FeaturesFinished, module, newIndexNamespace(module.SectionElementCount))
tp := newTypeUseParser(wasm.Features20220419, module, newIndexNamespace(module.SectionElementCount))
return tp, func(t *testing.T) {
// We should have inlined the type, and it is the first type use, which means the inlined index is zero
require.Zero(t, tp.inlinedTypeIndices[0].inlinedIdx)
@@ -196,7 +196,7 @@ func TestTypeUseParser_UnresolvedType(t *testing.T) {
}
runTypeUseParserTests(t, tests, func(tc *typeUseParserTest) (*typeUseParser, func(t *testing.T)) {
module := &wasm.Module{}
tp := newTypeUseParser(wasm.FeaturesFinished, module, newIndexNamespace(module.SectionElementCount))
tp := newTypeUseParser(wasm.Features20220419, module, newIndexNamespace(module.SectionElementCount))
return tp, func(t *testing.T) {
require.NotNil(t, tp.typeNamespace.unresolvedIndices)
if tc.expectedInlinedType == nil {
@@ -306,7 +306,7 @@ func TestTypeUseParser_ReuseExistingType(t *testing.T) {
require.NoError(t, err)
typeNamespace.count++
tp := newTypeUseParser(wasm.FeaturesFinished, module, typeNamespace)
tp := newTypeUseParser(wasm.Features20220419, module, typeNamespace)
return tp, func(t *testing.T) {
require.Zero(t, len(tp.typeNamespace.unresolvedIndices))
require.Zero(t, len(tp.inlinedTypes))
@@ -340,7 +340,7 @@ func TestTypeUseParser_ReuseExistingInlinedType(t *testing.T) {
}
runTypeUseParserTests(t, tests, func(tc *typeUseParserTest) (*typeUseParser, func(t *testing.T)) {
module := &wasm.Module{}
tp := newTypeUseParser(wasm.FeaturesFinished, module, newIndexNamespace(module.SectionElementCount))
tp := newTypeUseParser(wasm.Features20220419, module, newIndexNamespace(module.SectionElementCount))
// inline a type that doesn't match the test
require.NoError(t, parseTypeUse(tp, "((param i32 i64))", ignoreTypeUse))
// inline the test type
@@ -386,7 +386,7 @@ func TestTypeUseParser_BeginResets(t *testing.T) {
}
runTypeUseParserTests(t, tests, func(tc *typeUseParserTest) (*typeUseParser, func(t *testing.T)) {
module := &wasm.Module{}
tp := newTypeUseParser(wasm.FeaturesFinished, module, newIndexNamespace(module.SectionElementCount))
tp := newTypeUseParser(wasm.Features20220419, module, newIndexNamespace(module.SectionElementCount))
// inline a type that uses all fields
require.NoError(t, parseTypeUse(tp, "((type $i32i64_i32) (param $x i32) (param $y i64) (result i32))", ignoreTypeUse))
require.NoError(t, parseTypeUse(tp, tc.input, ignoreTypeUse))
@@ -510,13 +510,13 @@ func TestTypeUseParser_Errors(t *testing.T) {
{
name: "result second wrong",
input: "((result i32) (result i33))",
enabledFeatures: wasm.FeaturesFinished,
enabledFeatures: wasm.Features20220419,
expectedErr: "1:23: unknown type: i33",
},
{
name: "result second redundant type wrong",
input: "((result i32) (result i32 i33))",
enabledFeatures: wasm.FeaturesFinished,
enabledFeatures: wasm.Features20220419,
expectedErr: "1:27: unknown type: i33",
},
{
@@ -600,7 +600,7 @@ func TestTypeUseParser_FailsMatch(t *testing.T) {
require.NoError(t, err)
typeNamespace.count++
tp := newTypeUseParser(wasm.FeaturesFinished, module, typeNamespace)
tp := newTypeUseParser(wasm.Features20220419, module, typeNamespace)
tests := []struct{ name, source, expectedErr string }{
{
name: "nullary index",

View File

@@ -85,7 +85,7 @@ func TestCompile(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
enabledFeatures := tc.enabledFeatures
if enabledFeatures == 0 {
enabledFeatures = wasm.FeaturesFinished
enabledFeatures = wasm.Features20220419
}
res, err := CompileFunctions(ctx, enabledFeatures, tc.module)
@@ -487,7 +487,7 @@ func TestCompile_MultiValue(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
enabledFeatures := tc.enabledFeatures
if enabledFeatures == 0 {
enabledFeatures = wasm.FeaturesFinished
enabledFeatures = wasm.Features20220419
}
res, err := CompileFunctions(ctx, enabledFeatures, tc.module)
require.NoError(t, err)
@@ -550,7 +550,7 @@ func TestCompile_SignExtensionOps(t *testing.T) {
func requireCompilationResult(t *testing.T, enabledFeatures wasm.Features, expected *CompilationResult, module *wasm.Module) {
if enabledFeatures == 0 {
enabledFeatures = wasm.FeaturesFinished
enabledFeatures = wasm.Features20220419
}
res, err := CompileFunctions(ctx, enabledFeatures, module)
require.NoError(t, err)
@@ -558,7 +558,7 @@ func requireCompilationResult(t *testing.T, enabledFeatures wasm.Features, expec
}
func requireModuleText(t *testing.T, source string) *wasm.Module {
m, err := text.DecodeModule([]byte(source), wasm.FeaturesFinished, wasm.MemoryLimitPages)
m, err := text.DecodeModule([]byte(source), wasm.Features20220419, wasm.MemoryLimitPages)
require.NoError(t, err)
return m
}

View File

@@ -122,7 +122,11 @@ func NewRuntime() Runtime {
}
// NewRuntimeWithConfig returns a runtime with the given configuration.
func NewRuntimeWithConfig(config *RuntimeConfig) Runtime {
func NewRuntimeWithConfig(rConfig RuntimeConfig) Runtime {
config, ok := rConfig.(*runtimeConfig)
if !ok {
panic(fmt.Errorf("unsupported wazero.RuntimeConfig implementation: %#v", rConfig))
}
return &runtime{
store: wasm.NewStore(config.enabledFeatures, config.newEngine(config.enabledFeatures)),
enabledFeatures: config.enabledFeatures,

View File

@@ -18,6 +18,16 @@ import (
// testCtx is an arbitrary, non-default context. Non-nil also prevents linter errors.
var testCtx = context.WithValue(context.Background(), struct{}{}, "arbitrary")
func TestNewRuntimeWithConfig_PanicsOnWrongImpl(t *testing.T) {
// It is too burdensome to define an impl of RuntimeConfig in tests just to verify the error when it is wrong.
// Instead, we pass nil which is implicitly the wrong type, as that's less work!
err := require.CapturePanic(func() {
NewRuntimeWithConfig(nil)
})
require.EqualError(t, err, "unsupported wazero.RuntimeConfig implementation: <nil>")
}
func TestRuntime_CompileModule(t *testing.T) {
tests := []struct {
name string