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 }