// TODO replace with encoding/gob when reflection is ready func ReadArchive(packages map[string]*types.Package, filename, id string, data io.Reader) ([]byte, *types.Package, error) { r := bufio.NewReader(data) code, err := readUntilSeparator(r) if err != nil { return nil, nil, err } importList, err := readUntilSeparator(r) if err != nil { return nil, nil, err } pkg, err := gcimporter.ImportData(packages, filename, id, r) if err != nil { return nil, nil, err } var imports []*types.Package for _, path := range strings.Split(string(importList), "\n") { if path == "" { continue } impPkg, found := packages[path] if !found { impPkg = types.NewPackage(path, "", types.NewScope(nil)) packages[path] = impPkg } imports = append(imports, impPkg) } pkg.SetImports(imports) return code, pkg, nil }
func (p *importer) pkg() *types.Package { // if the package was seen before, i is its index (>= 0) i := p.int() if i >= 0 { return p.pkgList[i] } // otherwise, i is the package tag (< 0) if i != packageTag { panic(fmt.Sprintf("unexpected package tag %d", i)) } // read package data name := p.string() path := p.string() // if the package was imported before, use that one; otherwise create a new one pkg := p.imports[path] if pkg == nil { pkg = types.NewPackage(path, name, types.NewScope(nil)) p.imports[path] = pkg } p.pkgList = append(p.pkgList, pkg) return pkg }
// getPkg returns the package for a given id. If the package is // not found but we have a package name, create the package and // add it to the p.imports map. // func (p *parser) getPkg(id, name string) *types.Package { // package unsafe is not in the imports map - handle explicitly if id == "unsafe" { return types.Unsafe } pkg := p.imports[id] if pkg == nil && name != "" { pkg = types.NewPackage(id, name, types.NewScope(nil)) p.imports[id] = pkg } return pkg }
func tool() error { flag.Parse() cmd := flag.Arg(0) switch cmd { case "build": buildFlags := flag.NewFlagSet("build", flag.ContinueOnError) var pkgObj string buildFlags.StringVar(&pkgObj, "o", "", "") buildFlags.Parse(flag.Args()[1:]) if buildFlags.NArg() == 0 { wd, err := os.Getwd() if err != nil { return err } buildContext := &build.Context{ GOROOT: build.Default.GOROOT, GOPATH: build.Default.GOPATH, GOOS: build.Default.GOOS, GOARCH: "js", Compiler: "gc", } buildPkg, err := buildContext.ImportDir(wd, 0) if err != nil { return err } pkg := &Package{Package: buildPkg} pkg.ImportPath = wd if err := buildPackage(pkg); err != nil { return err } if pkgObj == "" { pkgObj = path.Base(wd) + ".js" } if err := writeCommandPackage(pkg, pkgObj); err != nil { return err } return nil } if strings.HasSuffix(buildFlags.Arg(0), ".go") { for _, arg := range buildFlags.Args() { if !strings.HasSuffix(arg, ".go") { return fmt.Errorf("named files must be .go files") } } if pkgObj == "" { basename := path.Base(buildFlags.Arg(0)) pkgObj = basename[:len(basename)-3] + ".js" } if err := buildFiles(buildFlags.Args(), pkgObj); err != nil { return err } return nil } for _, pkgPath := range buildFlags.Args() { buildPkg, err := buildImport(pkgPath, 0) if err != nil { return err } pkg := &Package{Package: buildPkg} if err := buildPackage(pkg); err != nil { return err } if pkgObj == "" { pkgObj = path.Base(buildFlags.Arg(0)) + ".js" } if err := writeCommandPackage(pkg, pkgObj); err != nil { return err } } return nil case "install": installFlags := flag.NewFlagSet("install", flag.ContinueOnError) installFlags.Parse(flag.Args()[1:]) installMode = true for _, pkgPath := range installFlags.Args() { buildPkg, err := buildImport(pkgPath, 0) if err != nil { return err } pkg := &Package{Package: buildPkg} if pkg.IsCommand() { pkg.PkgObj = pkg.BinDir + "/" + path.Base(pkg.ImportPath) + ".js" } if err := buildPackage(pkg); err != nil { return err } if err := writeCommandPackage(pkg, pkg.PkgObj); err != nil { return err } } return nil case "run": lastSourceArg := 1 for { if !strings.HasSuffix(flag.Arg(lastSourceArg), ".go") { break } lastSourceArg += 1 } if lastSourceArg == 1 { return fmt.Errorf("gopherjs run: no go files listed") } tempfile, err := ioutil.TempFile("", path.Base(flag.Arg(1))+".") if err != nil { return err } defer func() { tempfile.Close() os.Remove(tempfile.Name()) }() if err := buildFiles(flag.Args()[1:lastSourceArg], tempfile.Name()); err != nil { return err } if err := runNode(tempfile.Name(), flag.Args()[lastSourceArg:], ""); err != nil { return err } return nil case "test": testFlags := flag.NewFlagSet("test", flag.ContinueOnError) short := testFlags.Bool("short", false, "") verbose := testFlags.Bool("v", false, "") testFlags.Parse(flag.Args()[1:]) mainPkg := &Package{Package: &build.Package{ ImportPath: "main", }} packages["main"] = mainPkg mainPkgTypes := types.NewPackage("main", "main", types.NewScope(nil)) testingPkgTypes, _ := typesConfig.Import(typesConfig.Packages, "testing") mainPkgTypes.SetImports([]*types.Package{testingPkgTypes}) typesConfig.Packages["main"] = mainPkgTypes mainPkg.JavaScriptCode = []byte("Go$pkg.main = function() {\nGo$packages[\"flag\"].Parse();\n") for _, pkgPath := range testFlags.Args() { buildPkg, err := buildImport(pkgPath, 0) if err != nil { return err } pkg := &Package{Package: buildPkg} pkg.GoFiles = append(pkg.GoFiles, pkg.TestGoFiles...) if err := buildPackage(pkg); err != nil { return err } testPkg := &Package{Package: &build.Package{ ImportPath: pkg.ImportPath + "_test", Dir: pkg.Dir, GoFiles: pkg.XTestGoFiles, }} if err := buildPackage(testPkg); err != nil { return err } pkgTypes := typesConfig.Packages[pkg.ImportPath] testPkgTypes := typesConfig.Packages[testPkg.ImportPath] var names []string var tests []string for _, name := range pkgTypes.Scope().Names() { if strings.HasPrefix(name, "Test") { names = append(names, name) tests = append(tests, fmt.Sprintf(`Go$packages["%s"].%s`, pkg.ImportPath, name)) } } for _, name := range testPkgTypes.Scope().Names() { if strings.HasPrefix(name, "Test") { names = append(names, name) tests = append(tests, fmt.Sprintf(`Go$packages["%s"].%s`, testPkg.ImportPath, name)) } } mainPkg.JavaScriptCode = append(mainPkg.JavaScriptCode, []byte(fmt.Sprintf(`Go$packages["testing"].RunTests2("%s", "%s", ["%s"], [%s]);`+"\n", pkg.ImportPath, pkg.Dir, strings.Join(names, `", "`), strings.Join(tests, ", ")))...) mainPkgTypes.SetImports(append(mainPkgTypes.Imports(), pkgTypes, testPkgTypes)) } mainPkg.JavaScriptCode = append(mainPkg.JavaScriptCode, []byte("}; Go$pkg.init = function() {};")...) tempfile, err := ioutil.TempFile("", "test.") if err != nil { return err } defer func() { tempfile.Close() os.Remove(tempfile.Name()) }() if err := writeCommandPackage(mainPkg, tempfile.Name()); err != nil { return err } var args []string if *short { args = append(args, "-test.short") } if *verbose { args = append(args, "-test.v") } return runNode(tempfile.Name(), args, "") case "tool": tool := flag.Arg(1) toolFlags := flag.NewFlagSet("tool", flag.ContinueOnError) toolFlags.Bool("e", false, "") toolFlags.Bool("l", false, "") toolFlags.Bool("m", false, "") toolFlags.String("o", "", "") toolFlags.String("D", "", "") toolFlags.String("I", "", "") toolFlags.Parse(flag.Args()[2:]) if len(tool) == 2 { switch tool[1] { case 'g': basename := path.Base(toolFlags.Arg(0)) if err := buildFiles([]string{toolFlags.Arg(0)}, basename[:len(basename)-3]+".js"); err != nil { return err } return nil } } return fmt.Errorf("Tool not supported: " + tool) case "help", "": os.Stderr.WriteString(`GopherJS is a tool for compiling Go source code to JavaScript. Usage: gopherjs command [arguments] The commands are: build compile packages and dependencies install compile and install packages and dependencies run compile and run Go program `) return nil default: return fmt.Errorf("gopherjs: unknown subcommand \"%s\"\nRun 'gopherjs help' for usage.", cmd) } }