github.com/gopherjs/gopherjs@v1.19.0-beta1.0.20240506212314-27071a8796e4/compiler/compiler_test.go (about)

     1  package compiler
     2  
     3  import (
     4  	"bytes"
     5  	"go/ast"
     6  	"go/build"
     7  	"go/parser"
     8  	"go/token"
     9  	"go/types"
    10  	"testing"
    11  
    12  	"github.com/google/go-cmp/cmp"
    13  	"golang.org/x/tools/go/loader"
    14  )
    15  
    16  func TestOrder(t *testing.T) {
    17  	fileA := `
    18  package foo
    19  
    20  var Avar = "a"
    21  
    22  type Atype struct{}
    23  
    24  func Afunc() int {
    25  	var varA = 1
    26  	var varB = 2
    27  	return varA+varB
    28  }
    29  `
    30  
    31  	fileB := `
    32  package foo
    33  
    34  var Bvar = "b"
    35  
    36  type Btype struct{}
    37  
    38  func Bfunc() int {
    39  	var varA = 1
    40  	var varB = 2
    41  	return varA+varB
    42  }
    43  `
    44  	files := []source{{"fileA.go", []byte(fileA)}, {"fileB.go", []byte(fileB)}}
    45  
    46  	compare(t, "foo", files, false)
    47  	compare(t, "foo", files, true)
    48  }
    49  
    50  func compare(t *testing.T, path string, sourceFiles []source, minify bool) {
    51  	outputNormal, err := compile(path, sourceFiles, minify)
    52  	if err != nil {
    53  		t.Fatal(err)
    54  	}
    55  
    56  	// reverse the array
    57  	for i, j := 0, len(sourceFiles)-1; i < j; i, j = i+1, j-1 {
    58  		sourceFiles[i], sourceFiles[j] = sourceFiles[j], sourceFiles[i]
    59  	}
    60  
    61  	outputReversed, err := compile(path, sourceFiles, minify)
    62  	if err != nil {
    63  		t.Fatal(err)
    64  	}
    65  
    66  	if diff := cmp.Diff(string(outputNormal), string(outputReversed)); diff != "" {
    67  		t.Errorf("files in different order produce different JS:\n%s", diff)
    68  	}
    69  }
    70  
    71  type source struct {
    72  	name     string
    73  	contents []byte
    74  }
    75  
    76  func compile(path string, sourceFiles []source, minify bool) ([]byte, error) {
    77  	conf := loader.Config{}
    78  	conf.Fset = token.NewFileSet()
    79  	conf.ParserMode = parser.ParseComments
    80  
    81  	context := build.Default // make a copy of build.Default
    82  	conf.Build = &context
    83  	conf.Build.BuildTags = []string{"js"}
    84  
    85  	var astFiles []*ast.File
    86  	for _, sourceFile := range sourceFiles {
    87  		astFile, err := parser.ParseFile(conf.Fset, sourceFile.name, sourceFile.contents, parser.ParseComments)
    88  		if err != nil {
    89  			return nil, err
    90  		}
    91  		astFiles = append(astFiles, astFile)
    92  	}
    93  	conf.CreateFromFiles(path, astFiles...)
    94  	prog, err := conf.Load()
    95  	if err != nil {
    96  		return nil, err
    97  	}
    98  
    99  	archiveCache := map[string]*Archive{}
   100  	var importContext *ImportContext
   101  	importContext = &ImportContext{
   102  		Packages: make(map[string]*types.Package),
   103  		Import: func(path string) (*Archive, error) {
   104  			// find in local cache
   105  			if a, ok := archiveCache[path]; ok {
   106  				return a, nil
   107  			}
   108  
   109  			pi := prog.Package(path)
   110  			importContext.Packages[path] = pi.Pkg
   111  
   112  			// compile package
   113  			a, err := Compile(path, pi.Files, prog.Fset, importContext, minify)
   114  			if err != nil {
   115  				return nil, err
   116  			}
   117  			archiveCache[path] = a
   118  			return a, nil
   119  		},
   120  	}
   121  
   122  	a, err := importContext.Import(path)
   123  	if err != nil {
   124  		return nil, err
   125  	}
   126  	b, err := renderPackage(a)
   127  	if err != nil {
   128  		return nil, err
   129  	}
   130  	return b, nil
   131  }
   132  
   133  func renderPackage(archive *Archive) ([]byte, error) {
   134  	selection := make(map[*Decl]struct{})
   135  	for _, d := range archive.Declarations {
   136  		selection[d] = struct{}{}
   137  	}
   138  
   139  	buf := &bytes.Buffer{}
   140  
   141  	if err := WritePkgCode(archive, selection, goLinknameSet{}, false, &SourceMapFilter{Writer: buf}); err != nil {
   142  		return nil, err
   143  	}
   144  
   145  	return buf.Bytes(), nil
   146  }