Repository: tetratelabs/wazero
Pull request #341 (2022-03-07 05:15:35)

text: plumbs feature flags


Patch:
diff --git a/internal/wasm/text/decoder.go b/internal/wasm/text/decoder.go
index 6a00d079..cd3c5bc2 100644
--- a/internal/wasm/text/decoder.go
+++ b/internal/wasm/text/decoder.go
@@ -48,6 +48,9 @@ type moduleParser struct {
 	// source is the entire WebAssembly text format source code being parsed.
 	source []byte
 
+	// enabledFeatures ensure parsing errs at the correct line and column number when a feature is disabled.
+	enabledFeatures wasm.Features
+
 	// module holds the fields incrementally parsed from tokens in the source.
 	module *wasm.Module
 
@@ -99,7 +102,7 @@ type moduleParser struct {
 
 // DecodeModule implements internalwasm.DecodeModule for the WebAssembly 1.0 (20191205) Text Format
 // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#text-format%E2%91%A0
-func DecodeModule(source []byte, _ wasm.Features) (result *wasm.Module, err error) {
+func DecodeModule(source []byte, enabledFeatures wasm.Features) (result *wasm.Module, err error) {
 	// TODO: when globals are supported, err on mutable globals if disabled
 
 	// names are the wasm.Module NameSection
@@ -109,7 +112,7 @@ func DecodeModule(source []byte, _ wasm.Features) (result *wasm.Module, err erro
 	// * LocalNames: nil when no imported or module-defined function had named (param) fields.
 	names := &wasm.NameSection{}
 	module := &wasm.Module{NameSection: names}
-	p := newModuleParser(module)
+	p := newModuleParser(module, enabledFeatures)
 	p.source = source
 
 	// A valid source must begin with the token '(', but it could be preceded by whitespace or comments. For this
@@ -138,15 +141,15 @@ func DecodeModule(source []byte, _ wasm.Features) (result *wasm.Module, err erro
 	return module, nil
 }
 
-func newModuleParser(module *wasm.Module) *moduleParser {
-	p := moduleParser{module: module,
+func newModuleParser(module *wasm.Module, enabledFeatures wasm.Features) *moduleParser {
+	p := moduleParser{module: module, enabledFeatures: enabledFeatures,
 		typeNamespace:   newIndexNamespace(module.SectionElementCount),
 		funcNamespace:   newIndexNamespace(module.SectionElementCount),
 		memoryNamespace: newIndexNamespace(module.SectionElementCount),
 	}
 	p.typeParser = newTypeParser(p.typeNamespace, p.onTypeEnd)
 	p.typeUseParser = newTypeUseParser(module, p.typeNamespace)
-	p.funcParser = newFuncParser(p.typeUseParser, p.funcNamespace, p.endFunc)
+	p.funcParser = newFuncParser(enabledFeatures, p.typeUseParser, p.funcNamespace, p.endFunc)
 	p.memoryParser = newMemoryParser(p.memoryNamespace, p.endMemory)
 	return &p
 }
diff --git a/internal/wasm/text/func_parser.go b/internal/wasm/text/func_parser.go
index af3e00ed..b87080db 100644
--- a/internal/wasm/text/func_parser.go
+++ b/internal/wasm/text/func_parser.go
@@ -8,8 +8,8 @@ import (
 	wasm "github.com/tetratelabs/wazero/internal/wasm"
 )
 
-func newFuncParser(typeUseParser *typeUseParser, funcNamespace *indexNamespace, onFunc onFunc) *funcParser {
-	return &funcParser{typeUseParser: typeUseParser, funcNamespace: funcNamespace, onFunc: onFunc}
+func newFuncParser(enabledFeatures wasm.Features, typeUseParser *typeUseParser, funcNamespace *indexNamespace, onFunc onFunc) *funcParser {
+	return &funcParser{enabledFeatures: enabledFeatures, typeUseParser: typeUseParser, funcNamespace: funcNamespace, onFunc: onFunc}
 }
 
 type onFunc func(typeIdx wasm.Index, code *wasm.Code, name string, localNames wasm.NameMap) (tokenParser, error)
@@ -22,6 +22,9 @@ type onFunc func(typeIdx wasm.Index, code *wasm.Code, name string, localNames wa
 //
 // Note: funcParser is reusable. The caller resets via begin.
 type funcParser struct {
+	// enabledFeatures should be set to moduleParser.enabledFeatures
+	enabledFeatures wasm.Features
+
 	// onFunc is called when complete parsing the body. Unless testing, this should be moduleParser.onFuncEnd
 	onFunc onFunc
 


Test patch:
diff --git a/internal/wasm/text/decoder_test.go b/internal/wasm/text/decoder_test.go
index b64399f0..462a401d 100644
--- a/internal/wasm/text/decoder_test.go
+++ b/internal/wasm/text/decoder_test.go
@@ -2087,7 +2087,7 @@ func TestParseModule_Errors(t *testing.T) {
 }
 
 func TestModuleParser_ErrorContext(t *testing.T) {
-	p := newModuleParser(&wasm.Module{})
+	p := newModuleParser(&wasm.Module{}, 0)
 	tests := []struct {
 		input    string
 		pos      parserPosition
diff --git a/internal/wasm/text/func_parser_test.go b/internal/wasm/text/func_parser_test.go
index ff587d76..1b6904bd 100644
--- a/internal/wasm/text/func_parser_test.go
+++ b/internal/wasm/text/func_parser_test.go
@@ -11,8 +11,9 @@ import (
 
 func TestFuncParser(t *testing.T) {
 	tests := []struct {
-		name, source string
-		expected     *wasm.Code
+		name, source    string
+		enabledFeatures wasm.Features
+		expected        *wasm.Code
 	}{
 		{
 			name:     "empty",
@@ -52,7 +53,7 @@ func TestFuncParser(t *testing.T) {
 			}
 
 			module := &wasm.Module{}
-			fp := newFuncParser(&typeUseParser{module: module}, newIndexNamespace(module.SectionElementCount), setFunc)
+			fp := newFuncParser(tc.enabledFeatures, &typeUseParser{module: module}, newIndexNamespace(module.SectionElementCount), setFunc)
 			require.NoError(t, parseFunc(fp, tc.source))
 			require.Equal(t, tc.expected, parsedCode)
 		})
@@ -62,6 +63,7 @@ func TestFuncParser(t *testing.T) {
 func TestFuncParser_Call_Unresolved(t *testing.T) {
 	tests := []struct {
 		name, source            string
+		enabledFeatures         wasm.Features
 		expectedCode            *wasm.Code
 		expectedUnresolvedIndex *unresolvedIndex
 	}{
@@ -110,7 +112,7 @@ func TestFuncParser_Call_Unresolved(t *testing.T) {
 			}
 
 			module := &wasm.Module{}
-			fp := newFuncParser(&typeUseParser{module: module}, newIndexNamespace(module.SectionElementCount), setFunc)
+			fp := newFuncParser(tc.enabledFeatures, &typeUseParser{module: module}, newIndexNamespace(module.SectionElementCount), setFunc)
 			require.NoError(t, parseFunc(fp, tc.source))
 			require.Equal(t, tc.expectedCode, parsedCode)
 			require.Equal(t, []*unresolvedIndex{tc.expectedUnresolvedIndex}, fp.funcNamespace.unresolvedIndices)
@@ -120,8 +122,9 @@ func TestFuncParser_Call_Unresolved(t *testing.T) {
 
 func TestFuncParser_Call_Resolved(t *testing.T) {
 	tests := []struct {
-		name, source string
-		expected     *wasm.Code
+		name, source    string
+		enabledFeatures wasm.Features
+		expected        *wasm.Code
 	}{
 		{
 			name:     "index zero",
@@ -170,7 +173,7 @@ func TestFuncParser_Call_Resolved(t *testing.T) {
 				return parseErr, nil
 			}
 
-			fp := newFuncParser(&typeUseParser{module: &wasm.Module{}}, funcNamespace, setFunc)
+			fp := newFuncParser(tc.enabledFeatures, &typeUseParser{module: &wasm.Module{}}, funcNamespace, setFunc)
 			require.NoError(t, parseFunc(fp, tc.source))
 			require.Equal(t, tc.expected, parsedCode)
 		})
@@ -179,7 +182,9 @@ func TestFuncParser_Call_Resolved(t *testing.T) {
 
 func TestFuncParser_Errors(t *testing.T) {
 	tests := []struct {
-		name, source, expectedErr string
+		name, source    string
+		enabledFeatures wasm.Features
+		expectedErr     string
 	}{
 		{
 			name:        "not field",
@@ -228,7 +233,7 @@ func TestFuncParser_Errors(t *testing.T) {
 
 		t.Run(tc.name, func(t *testing.T) {
 			module := &wasm.Module{}
-			fp := newFuncParser(&typeUseParser{module: module}, newIndexNamespace(module.SectionElementCount), failOnFunc)
+			fp := newFuncParser(tc.enabledFeatures, &typeUseParser{module: module}, newIndexNamespace(module.SectionElementCount), failOnFunc)
 			require.EqualError(t, parseFunc(fp, tc.source), tc.expectedErr)
 		})
 	}