github.com/goplusjs/gopherjs@v1.2.6-0.20211206034512-f187917453b8/build/go116_embed.go (about)

     1  // +build go1.16
     2  
     3  package build
     4  
     5  import (
     6  	"bytes"
     7  	"fmt"
     8  	"go/ast"
     9  	"go/parser"
    10  	"go/token"
    11  	"strings"
    12  
    13  	"github.com/visualfc/goembed"
    14  )
    15  
    16  func buildIdent(name string) string {
    17  	return fmt.Sprintf("__js_embed_%x__", name)
    18  }
    19  
    20  var embed_head = `package $pkg
    21  
    22  import (
    23  	"embed"
    24  	_ "unsafe"
    25  )
    26  
    27  //go:linkname gopherjs_embed_buildFS embed.buildFS
    28  func gopherjs_embed_buildFS(list []struct {
    29  	name string
    30  	data string
    31  	hash [16]byte
    32  }) (f embed.FS)
    33  `
    34  
    35  func (s *Session) checkEmbed(pkg *PackageData, fset *token.FileSet, files []*ast.File) (*ast.File, error) {
    36  	if len(pkg.EmbedPatternPos) == 0 {
    37  		return nil, nil
    38  	}
    39  	ems := goembed.CheckEmbed(pkg.EmbedPatternPos, fset, files)
    40  	if len(ems) == 0 {
    41  		return nil, nil
    42  	}
    43  	r := goembed.NewResolve()
    44  	var buf bytes.Buffer
    45  	buf.WriteString(strings.Replace(embed_head, "$pkg", pkg.Name, 1))
    46  	buf.WriteString("\nvar (\n")
    47  	for _, v := range ems {
    48  		v.Spec.Names[0].Name = "_"
    49  		fs, _ := r.Load(pkg.Dir, v)
    50  		switch v.Kind {
    51  		case goembed.EmbedBytes:
    52  			buf.WriteString(fmt.Sprintf("\t%v = []byte(%v)\n", v.Name, buildIdent(fs[0].Name)))
    53  		case goembed.EmbedString:
    54  			buf.WriteString(fmt.Sprintf("\t%v = %v\n", v.Name, buildIdent(fs[0].Name)))
    55  		case goembed.EmbedFiles:
    56  			fs = goembed.BuildFS(fs)
    57  			buf.WriteString(fmt.Sprintf("\t%v=", v.Name))
    58  			buf.WriteString(`gopherjs_embed_buildFS(
    59  []struct {
    60  	name string
    61  	data string
    62  	hash [16]byte
    63  }{
    64  `)
    65  			for _, f := range fs {
    66  				if len(f.Data) == 0 {
    67  					buf.WriteString(fmt.Sprintf("\t{\"%v\",\"\",[16]byte{}},\n",
    68  						f.Name))
    69  				} else {
    70  					buf.WriteString(fmt.Sprintf("\t{\"%v\",%v,[16]byte{%v}},\n",
    71  						f.Name, buildIdent(f.Name), goembed.BytesToList(f.Hash[:])))
    72  				}
    73  			}
    74  			buf.WriteString("})\n")
    75  		}
    76  	}
    77  	buf.WriteString("\n)\n")
    78  	buf.WriteString("\nvar (\n")
    79  	for _, f := range r.Files() {
    80  		if len(f.Data) == 0 {
    81  			buf.WriteString(fmt.Sprintf("\t%v string\n",
    82  				buildIdent(f.Name)))
    83  		} else {
    84  			buf.WriteString(fmt.Sprintf("\t%v = string(\"%v\")\n",
    85  				buildIdent(f.Name), goembed.BytesToHex(f.Data)))
    86  		}
    87  	}
    88  	buf.WriteString(")\n\n")
    89  	f, err := parser.ParseFile(fset, "js_embed.go", buf.String(), parser.ParseComments)
    90  	if err != nil {
    91  		return nil, err
    92  	}
    93  	return f, nil
    94  }