func (s *Session) BuildPackage(pkg *PackageData) error { s.Packages[pkg.ImportPath] = pkg if pkg.ImportPath == "unsafe" { return nil } if pkg.PkgObj != "" { var fileInfo os.FileInfo gopherjsBinary, err := osext.Executable() if err == nil { fileInfo, err = os.Stat(gopherjsBinary) if err == nil { pkg.SrcModTime = fileInfo.ModTime() } } if err != nil { os.Stderr.WriteString("Could not get GopherJS binary's modification timestamp. Please report issue.\n") pkg.SrcModTime = time.Now() } for _, importedPkgPath := range pkg.Imports { ignored := true for _, pos := range pkg.ImportPos[importedPkgPath] { importFile := filepath.Base(pos.Filename) for _, file := range pkg.GoFiles { if importFile == file { ignored = false break } } if !ignored { break } } if importedPkgPath == "unsafe" || ignored { continue } _, err := s.ImportPackage(importedPkgPath) if err != nil { return err } impModeTime := s.Packages[importedPkgPath].SrcModTime if impModeTime.After(pkg.SrcModTime) { pkg.SrcModTime = impModeTime } } for _, name := range pkg.GoFiles { fileInfo, err := os.Stat(filepath.Join(pkg.Dir, name)) if err != nil { return err } if fileInfo.ModTime().After(pkg.SrcModTime) { pkg.SrcModTime = fileInfo.ModTime() } } pkgObjFileInfo, err := os.Stat(pkg.PkgObj) if err == nil && !pkg.SrcModTime.After(pkgObjFileInfo.ModTime()) { // package object is up to date, load from disk if library pkg.UpToDate = true if pkg.IsCommand() { return nil } objFile, err := ioutil.ReadFile(pkg.PkgObj) if err != nil { return err } pkg.Archive, err = compiler.UnmarshalArchive(pkg.PkgObj, pkg.ImportPath, objFile, s.ImportContext) if err != nil { return err } return nil } } fileSet := token.NewFileSet() files, err := Parse(pkg.Package, fileSet) if err != nil { return err } pkg.Archive, err = compiler.Compile(pkg.ImportPath, files, fileSet, s.ImportContext, s.options.Minify) if err != nil { return err } if s.options.Verbose { fmt.Println(pkg.ImportPath) } if pkg.PkgObj == "" || pkg.IsCommand() { return nil } if err := s.writeLibraryPackage(pkg, pkg.PkgObj); err != nil { if strings.HasPrefix(pkg.PkgObj, s.options.GOROOT) { // fall back to first GOPATH workspace firstGopathWorkspace := filepath.SplitList(s.options.GOPATH)[0] if err := s.writeLibraryPackage(pkg, filepath.Join(firstGopathWorkspace, pkg.PkgObj[len(s.options.GOROOT):])); err != nil { return err } return nil } return err } return nil }
func control(scope *angularjs.Scope) { scope.Set("code", initCode) // scope.Set("showGenerated", false) // scope.Set("generated", `(generated code will be shown here after clicking "Run")`) packages := make(map[string]*compiler.Archive) var pkgsToLoad []string importContext := compiler.NewImportContext( func(path string) (*compiler.Archive, error) { if pkg, found := packages[path]; found { return pkg, nil } pkgsToLoad = append(pkgsToLoad, path) return &compiler.Archive{}, nil }, ) fileSet := token.NewFileSet() pkgsReceived := 0 setupEnvironment(scope) var run func(bool) run = func(loadOnly bool) { output = nil scope.Set("output", output) pkgsToLoad = nil file, err := parser.ParseFile(fileSet, "prog.go", getCode(), parser.ParseComments, ) if err != nil { if list, ok := err.(scanner.ErrorList); ok { for _, entry := range list { output = append(output, errErrLine(entry)) } scope.Set("output", output) return } scope.Set("output", []Line{errErrLine(err)}) return } mainPkg, err := compiler.Compile("main", []*ast.File{file}, fileSet, importContext, false, ) packages["main"] = mainPkg if err != nil && len(pkgsToLoad) == 0 { if list, ok := err.(compiler.ErrorList); ok { output := make([]Line, 0) for _, entry := range list { output = append(output, errErrLine(entry)) } scope.Set("output", output) return } scope.Set("output", []Line{errErrLine(err)}) return } var allPkgs []*compiler.Archive if len(pkgsToLoad) == 0 { for _, depPath := range mainPkg.Dependencies { dep, _ := importContext.Import(string(depPath)) allPkgs = append(allPkgs, dep) } allPkgs = append(allPkgs, mainPkg) } if len(pkgsToLoad) != 0 { pkgsReceived = 0 for _, p := range pkgsToLoad { path := p req := js.Global.Get("XMLHttpRequest").New() req.Call("open", "GET", "pkg/"+path+".a", true) req.Set("responseType", "arraybuffer") req.Set("onload", func() { if req.Get("status").Int() != 200 { f := func() { emsg := fmt.Sprintf("cannot load package \"%s\"", path) scope.Set("output", []Line{errLine(emsg)}) } scope.Apply(f) return } data := js.Global.Get("Uint8Array").New(req.Get("response")).Interface().([]byte) packages[path], err = compiler.UnmarshalArchive( path+".a", path, []byte(data), importContext, ) if err != nil { scope.Apply(func() { scope.Set("output", []Line{errErrLine(err)}) }) return } pkgsReceived++ if pkgsReceived == len(pkgsToLoad) { run(loadOnly) } }) req.Call("send") } return } if loadOnly { return } mainPkgCode := bytes.NewBuffer(nil) compiler.WritePkgCode(packages["main"], false, &compiler.SourceMapFilter{Writer: mainPkgCode}, ) // scope.Set("generated", mainPkgCode.String()) jsCode := bytes.NewBuffer(nil) jsCode.WriteString("try{\n") compiler.WriteProgramCode(allPkgs, importContext, &compiler.SourceMapFilter{Writer: jsCode}, ) jsCode.WriteString("} catch (err) {\ngoPanicHandler(err.message);\n}\n") js.Global.Call("eval", js.InternalObject(jsCode.String())) } scope.Set("run", run) run(true) scope.Set("format", func() { out, err := format.Source(getCode()) if err != nil { scope.Set("output", []Line{errErrLine(err)}) return } setCode(string(out)) scope.Set("output", []Line{}) }) }