@@ -21,8 +21,11 @@ import (
21
21
22
22
"github.com/fsnotify/fsnotify"
23
23
"github.com/gopherjs/gopherjs/compiler"
24
+ "github.com/gopherjs/gopherjs/compiler/gopherjspkg"
24
25
"github.com/gopherjs/gopherjs/compiler/natives"
25
26
"github.com/neelance/sourcemap"
27
+ "github.com/shurcooL/httpfs/vfsutil"
28
+ "golang.org/x/tools/go/buildutil"
26
29
)
27
30
28
31
type ImportCError struct {
@@ -35,7 +38,11 @@ func (e *ImportCError) Error() string {
35
38
36
39
// NewBuildContext creates a build context for building Go packages
37
40
// with GopherJS compiler.
41
+ //
42
+ // Core GopherJS packages (i.e., "github.com/gopherjs/gopherjs/js", "github.com/gopherjs/gopherjs/nosync")
43
+ // are loaded from gopherjspkg.FS virtual filesystem rather than GOPATH.
38
44
func NewBuildContext (installSuffix string , buildTags []string ) * build.Context {
45
+ gopherjsRoot := filepath .Join (build .Default .GOROOT , "src" , "github.com" , "gopherjs" , "gopherjs" )
39
46
return & build.Context {
40
47
GOROOT : build .Default .GOROOT ,
41
48
GOPATH : build .Default .GOPATH ,
@@ -49,7 +56,50 @@ func NewBuildContext(installSuffix string, buildTags []string) *build.Context {
49
56
),
50
57
ReleaseTags : build .Default .ReleaseTags ,
51
58
CgoEnabled : true , // detect `import "C"` to throw proper error
59
+
60
+ IsDir : func (path string ) bool {
61
+ if strings .HasPrefix (path , gopherjsRoot + string (filepath .Separator )) {
62
+ path = filepath .ToSlash (path [len (gopherjsRoot ):])
63
+ if fi , err := vfsutil .Stat (gopherjspkg .FS , path ); err == nil {
64
+ return fi .IsDir ()
65
+ }
66
+ }
67
+ fi , err := os .Stat (path )
68
+ return err == nil && fi .IsDir ()
69
+ },
70
+ ReadDir : func (path string ) ([]os.FileInfo , error ) {
71
+ if strings .HasPrefix (path , gopherjsRoot + string (filepath .Separator )) {
72
+ path = filepath .ToSlash (path [len (gopherjsRoot ):])
73
+ if fis , err := vfsutil .ReadDir (gopherjspkg .FS , path ); err == nil {
74
+ return fis , nil
75
+ }
76
+ }
77
+ return ioutil .ReadDir (path )
78
+ },
79
+ OpenFile : func (path string ) (io.ReadCloser , error ) {
80
+ if strings .HasPrefix (path , gopherjsRoot + string (filepath .Separator )) {
81
+ path = filepath .ToSlash (path [len (gopherjsRoot ):])
82
+ if f , err := gopherjspkg .FS .Open (path ); err == nil {
83
+ return f , nil
84
+ }
85
+ }
86
+ return os .Open (path )
87
+ },
88
+ }
89
+ }
90
+
91
+ // statFile returns an os.FileInfo describing the named file.
92
+ // For files in "$GOROOT/src/github.com/gopherjs/gopherjs" directory,
93
+ // gopherjspkg.FS is consulted first.
94
+ func statFile (path string ) (os.FileInfo , error ) {
95
+ gopherjsRoot := filepath .Join (build .Default .GOROOT , "src" , "github.com" , "gopherjs" , "gopherjs" )
96
+ if strings .HasPrefix (path , gopherjsRoot + string (filepath .Separator )) {
97
+ path = filepath .ToSlash (path [len (gopherjsRoot ):])
98
+ if fi , err := vfsutil .Stat (gopherjspkg .FS , path ); err == nil {
99
+ return fi , nil
100
+ }
52
101
}
102
+ return os .Stat (path )
53
103
}
54
104
55
105
// Import returns details about the Go package named by the import path. If the
@@ -138,7 +188,7 @@ func importWithSrcDir(bctx build.Context, path string, srcDir string, mode build
138
188
}
139
189
}
140
190
141
- jsFiles , err := jsFilesFromDir (pkg .Dir )
191
+ jsFiles , err := jsFilesFromDir (& bctx , pkg .Dir )
142
192
if err != nil {
143
193
return nil , err
144
194
}
@@ -177,12 +227,13 @@ Outer:
177
227
// ImportDir is like Import but processes the Go package found in the named
178
228
// directory.
179
229
func ImportDir (dir string , mode build.ImportMode , installSuffix string , buildTags []string ) (* PackageData , error ) {
180
- pkg , err := NewBuildContext (installSuffix , buildTags ).ImportDir (dir , mode )
230
+ bctx := NewBuildContext (installSuffix , buildTags )
231
+ pkg , err := bctx .ImportDir (dir , mode )
181
232
if err != nil {
182
233
return nil , err
183
234
}
184
235
185
- jsFiles , err := jsFilesFromDir (pkg .Dir )
236
+ jsFiles , err := jsFilesFromDir (bctx , pkg .Dir )
186
237
if err != nil {
187
238
return nil , err
188
239
}
@@ -201,7 +252,7 @@ func ImportDir(dir string, mode build.ImportMode, installSuffix string, buildTag
201
252
// as an existing file from the standard library). For all identifiers that exist
202
253
// in the original AND the overrides, the original identifier in the AST gets
203
254
// replaced by `_`. New identifiers that don't exist in original package get added.
204
- func parseAndAugment (pkg * build.Package , isTest bool , fileSet * token.FileSet ) ([]* ast.File , error ) {
255
+ func parseAndAugment (bctx * build. Context , pkg * build.Package , isTest bool , fileSet * token.FileSet ) ([]* ast.File , error ) {
205
256
var files []* ast.File
206
257
replacedDeclNames := make (map [string ]bool )
207
258
funcName := func (d * ast.FuncDecl ) string {
@@ -305,10 +356,10 @@ func parseAndAugment(pkg *build.Package, isTest bool, fileSet *token.FileSet) ([
305
356
306
357
var errList compiler.ErrorList
307
358
for _ , name := range pkg .GoFiles {
308
- if ! filepath .IsAbs (name ) {
359
+ if ! filepath .IsAbs (name ) { // name might be absolute if specified directly. E.g., `gopherjs build /abs/file.go`.
309
360
name = filepath .Join (pkg .Dir , name )
310
361
}
311
- r , err := os . Open ( name )
362
+ r , err := buildutil . OpenFile ( bctx , name )
312
363
if err != nil {
313
364
return nil , err
314
365
}
@@ -466,7 +517,7 @@ func (s *Session) BuildDir(packagePath string, importPath string, pkgObj string)
466
517
return err
467
518
}
468
519
pkg := & PackageData {Package : buildPkg }
469
- jsFiles , err := jsFilesFromDir (pkg .Dir )
520
+ jsFiles , err := jsFilesFromDir (s . bctx , pkg .Dir )
470
521
if err != nil {
471
522
return err
472
523
}
@@ -585,7 +636,7 @@ func (s *Session) BuildPackage(pkg *PackageData) (*compiler.Archive, error) {
585
636
}
586
637
587
638
for _ , name := range append (pkg .GoFiles , pkg .JSFiles ... ) {
588
- fileInfo , err := os . Stat (filepath .Join (pkg .Dir , name ))
639
+ fileInfo , err := statFile (filepath .Join (pkg .Dir , name ))
589
640
if err != nil {
590
641
return nil , err
591
642
}
@@ -619,7 +670,7 @@ func (s *Session) BuildPackage(pkg *PackageData) (*compiler.Archive, error) {
619
670
}
620
671
621
672
fileSet := token .NewFileSet ()
622
- files , err := parseAndAugment (pkg .Package , pkg .IsTest , fileSet )
673
+ files , err := parseAndAugment (s . bctx , pkg .Package , pkg .IsTest , fileSet )
623
674
if err != nil {
624
675
return nil , err
625
676
}
@@ -757,8 +808,8 @@ func NewMappingCallback(m *sourcemap.Map, goroot, gopath string, localMap bool)
757
808
}
758
809
}
759
810
760
- func jsFilesFromDir (dir string ) ([]string , error ) {
761
- files , err := ioutil .ReadDir (dir )
811
+ func jsFilesFromDir (bctx * build. Context , dir string ) ([]string , error ) {
812
+ files , err := buildutil .ReadDir (bctx , dir )
762
813
if err != nil {
763
814
return nil , err
764
815
}
0 commit comments