@@ -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
@@ -137,7 +187,7 @@ func importWithSrcDir(bctx *build.Context, path string, srcDir string, mode buil
137
187
}
138
188
}
139
189
140
- jsFiles , err := jsFilesFromDir (pkg .Dir )
190
+ jsFiles , err := jsFilesFromDir (bctx , pkg .Dir )
141
191
if err != nil {
142
192
return nil , err
143
193
}
@@ -176,12 +226,13 @@ Outer:
176
226
// ImportDir is like Import but processes the Go package found in the named
177
227
// directory.
178
228
func ImportDir (dir string , mode build.ImportMode , installSuffix string , buildTags []string ) (* PackageData , error ) {
179
- pkg , err := NewBuildContext (installSuffix , buildTags ).ImportDir (dir , mode )
229
+ bctx := NewBuildContext (installSuffix , buildTags )
230
+ pkg , err := bctx .ImportDir (dir , mode )
180
231
if err != nil {
181
232
return nil , err
182
233
}
183
234
184
- jsFiles , err := jsFilesFromDir (pkg .Dir )
235
+ jsFiles , err := jsFilesFromDir (bctx , pkg .Dir )
185
236
if err != nil {
186
237
return nil , err
187
238
}
@@ -200,7 +251,7 @@ func ImportDir(dir string, mode build.ImportMode, installSuffix string, buildTag
200
251
// as an existing file from the standard library). For all identifiers that exist
201
252
// in the original AND the overrides, the original identifier in the AST gets
202
253
// replaced by `_`. New identifiers that don't exist in original package get added.
203
- func parseAndAugment (pkg * build.Package , isTest bool , fileSet * token.FileSet ) ([]* ast.File , error ) {
254
+ func parseAndAugment (bctx * build. Context , pkg * build.Package , isTest bool , fileSet * token.FileSet ) ([]* ast.File , error ) {
204
255
var files []* ast.File
205
256
replacedDeclNames := make (map [string ]bool )
206
257
funcName := func (d * ast.FuncDecl ) string {
@@ -304,10 +355,10 @@ func parseAndAugment(pkg *build.Package, isTest bool, fileSet *token.FileSet) ([
304
355
305
356
var errList compiler.ErrorList
306
357
for _ , name := range pkg .GoFiles {
307
- if ! filepath .IsAbs (name ) {
358
+ if ! filepath .IsAbs (name ) { // name might be absolute if specified directly. E.g., `gopherjs build /abs/file.go`.
308
359
name = filepath .Join (pkg .Dir , name )
309
360
}
310
- r , err := os . Open ( name )
361
+ r , err := buildutil . OpenFile ( bctx , name )
311
362
if err != nil {
312
363
return nil , err
313
364
}
@@ -465,7 +516,7 @@ func (s *Session) BuildDir(packagePath string, importPath string, pkgObj string)
465
516
return err
466
517
}
467
518
pkg := & PackageData {Package : buildPkg }
468
- jsFiles , err := jsFilesFromDir (pkg .Dir )
519
+ jsFiles , err := jsFilesFromDir (s . bctx , pkg .Dir )
469
520
if err != nil {
470
521
return err
471
522
}
@@ -584,7 +635,7 @@ func (s *Session) BuildPackage(pkg *PackageData) (*compiler.Archive, error) {
584
635
}
585
636
586
637
for _ , name := range append (pkg .GoFiles , pkg .JSFiles ... ) {
587
- fileInfo , err := os . Stat (filepath .Join (pkg .Dir , name ))
638
+ fileInfo , err := statFile (filepath .Join (pkg .Dir , name ))
588
639
if err != nil {
589
640
return nil , err
590
641
}
@@ -618,7 +669,7 @@ func (s *Session) BuildPackage(pkg *PackageData) (*compiler.Archive, error) {
618
669
}
619
670
620
671
fileSet := token .NewFileSet ()
621
- files , err := parseAndAugment (pkg .Package , pkg .IsTest , fileSet )
672
+ files , err := parseAndAugment (s . bctx , pkg .Package , pkg .IsTest , fileSet )
622
673
if err != nil {
623
674
return nil , err
624
675
}
@@ -756,8 +807,8 @@ func NewMappingCallback(m *sourcemap.Map, goroot, gopath string, localMap bool)
756
807
}
757
808
}
758
809
759
- func jsFilesFromDir (dir string ) ([]string , error ) {
760
- files , err := ioutil .ReadDir (dir )
810
+ func jsFilesFromDir (bctx * build. Context , dir string ) ([]string , error ) {
811
+ files , err := buildutil .ReadDir (bctx , dir )
761
812
if err != nil {
762
813
return nil , err
763
814
}
0 commit comments