├── .circleci └── config.yml ├── .gitignore ├── .std_test_pkg_exclusions ├── .vet_exclusions ├── LICENSE ├── README.md ├── build ├── build.go └── build_test.go ├── compiler ├── analysis │ ├── bool.go │ ├── break.go │ ├── escape.go │ ├── info.go │ └── sideeffect.go ├── astutil │ └── astutil.go ├── compiler.go ├── expressions.go ├── filter │ ├── assign.go │ └── incdecstmt.go ├── gopherjspkg │ ├── doc.go │ ├── fs.go │ └── fs_vfsdata.go ├── natives │ ├── doc.go │ ├── fs.go │ ├── fs_vfsdata.go │ └── src │ │ ├── bytes │ │ ├── bytes.go │ │ └── bytes_test.go │ │ ├── crypto │ │ ├── internal │ │ │ └── subtle │ │ │ │ └── aliasing.go │ │ ├── rand │ │ │ └── rand.go │ │ └── x509 │ │ │ ├── x509.go │ │ │ └── x509_test.go │ │ ├── database │ │ └── sql │ │ │ └── driver │ │ │ └── driver_test.go │ │ ├── debug │ │ └── elf │ │ │ └── elf_test.go │ │ ├── encoding │ │ ├── gob │ │ │ └── gob_test.go │ │ └── json │ │ │ └── stream_test.go │ │ ├── fmt │ │ └── fmt_test.go │ │ ├── go │ │ └── token │ │ │ └── token_test.go │ │ ├── internal │ │ ├── bytealg │ │ │ └── bytealg.go │ │ ├── cpu │ │ │ └── cpu.go │ │ ├── fmtsort │ │ │ └── fmtsort_test.go │ │ ├── poll │ │ │ └── fd_poll.go │ │ ├── syscall │ │ │ └── unix │ │ │ │ └── unix.go │ │ └── testenv │ │ │ └── testenv.go │ │ ├── io │ │ └── io_test.go │ │ ├── math │ │ ├── big │ │ │ ├── big.go │ │ │ └── big_test.go │ │ ├── bits │ │ │ └── bits.go │ │ ├── math.go │ │ ├── math_test.go │ │ └── rand │ │ │ └── rand_test.go │ │ ├── net │ │ ├── http │ │ │ ├── cookiejar │ │ │ │ └── example_test.go │ │ │ ├── fetch.go │ │ │ └── http.go │ │ └── net.go │ │ ├── os │ │ ├── os.go │ │ └── signal │ │ │ └── signal.go │ │ ├── reflect │ │ ├── example_test.go │ │ ├── reflect.go │ │ ├── reflect_go111.go │ │ ├── reflect_go1111.go │ │ ├── reflect_test.go │ │ └── swapper.go │ │ ├── regexp │ │ └── regexp_test.go │ │ ├── runtime │ │ ├── debug │ │ │ └── debug.go │ │ ├── internal │ │ │ └── sys │ │ │ │ └── sys.go │ │ ├── pprof │ │ │ └── pprof.go │ │ └── runtime.go │ │ ├── strings │ │ ├── strings.go │ │ └── strings_test.go │ │ ├── sync │ │ ├── atomic │ │ │ ├── atomic.go │ │ │ └── atomic_test.go │ │ ├── cond.go │ │ ├── export_test.go │ │ ├── pool.go │ │ ├── sync.go │ │ ├── sync_test.go │ │ └── waitgroup.go │ │ ├── syscall │ │ ├── js │ │ │ └── js.go │ │ ├── syscall.go │ │ ├── syscall_darwin.go │ │ ├── syscall_linux.go │ │ ├── syscall_nonlinux.go │ │ ├── syscall_unix.go │ │ └── syscall_windows.go │ │ ├── testing │ │ ├── example.go │ │ ├── ioutil.go │ │ └── testing.go │ │ ├── text │ │ └── template │ │ │ └── template.go │ │ ├── time │ │ └── time.go │ │ └── unicode │ │ └── unicode.go ├── package.go ├── prelude │ ├── formatpreludejs.go │ ├── generate.go │ ├── genprelude.go │ ├── goroutines.js │ ├── jsmapping.js │ ├── numeric.js │ ├── prelude.go │ ├── prelude.js │ ├── prelude_min.go │ ├── prettier_options.json │ ├── types.js │ └── uglifyjs_options.json ├── statements.go ├── typesutil │ └── typesutil.go ├── utils.go └── version_check.go ├── doc ├── packages.md └── syscalls.md ├── genmodstubbs.go ├── go.mod ├── go.sum ├── internal └── sysutil │ ├── sysutil.go │ └── sysutil_windows.go ├── js └── js.go ├── node-syscall ├── binding.gyp └── syscall.cc ├── nosync ├── map.go ├── mutex.go ├── once.go └── pool.go ├── package-lock.json ├── package.json ├── script_test.go ├── testdata ├── build.txt ├── build_gopath.txt ├── compile_error.txt ├── compiler_unused_nil_assign.txt ├── help.txt ├── install.txt ├── install_gopath.txt ├── mod │ ├── example.com_hello_v1.0.0.txt │ ├── github.com_fsnotify_fsnotify_v1.4.7.txt │ ├── github.com_gopherjs_gopherjs_v0.0.0.txt │ ├── github.com_inconshreveable_mousetrap_v1.0.0.txt │ ├── github.com_neelance_astrewrite_v0.0.0-20160511093645-99348263ae86.txt │ ├── github.com_neelance_sourcemap_v0.0.0-20151028013722-8c68805598ab.txt │ ├── github.com_rogpeppe_go-internal_v1.0.1-alpha.1.txt │ ├── github.com_shurcoo!l_go_v0.0.0-20180423040247-9e1955d9fb6e.txt │ ├── github.com_shurcoo!l_httpfs_v0.0.0-20181222201310-74dc9339e414.txt │ ├── github.com_shurcoo!l_vfsgen_v0.0.0-20180915214035-33ae1944be3f.txt │ ├── github.com_spf13_cobra_v0.0.3.txt │ ├── github.com_spf13_pflag_v1.0.1.txt │ ├── golang.org_x_crypto_v0.0.0-20180807104621-f027049dab0a.txt │ ├── golang.org_x_sys_v0.0.0-20180807162357-acbc56fc7007.txt │ └── golang.org_x_tools_v0.0.0-20190308142131-b40df0fb21c3.txt ├── modified_changed.txt ├── run.txt ├── run_gopath.txt ├── serve.txt ├── serve_gopath.txt ├── shadow.txt ├── stdlib_vendor_import.txt ├── test.txt ├── test_gopath.txt ├── vendor_gopath.txt └── version.txt ├── tests ├── alias_test.go ├── compiler_test.go ├── copy_test.go ├── deferblock_test.go ├── doc.go ├── goroutine_test.go ├── js_test.go ├── lowlevel_test.go ├── main │ ├── main.go │ └── main_test.go ├── misc_test.go ├── otherpkg │ └── otherpkg.go ├── run.go ├── sort_test.go ├── syscalljs │ └── js_test.go └── testdata │ ├── time_inexternalization.go │ └── time_inexternalization.out ├── tool.go ├── tool_deps.go └── tools.go /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | working_directory: /go/gopherjs 5 | docker: 6 | # We have a custom installation of Go below so this version is (largely) irrelevant. 7 | - image: circleci/golang:1.10 8 | 9 | environment: 10 | NVM_VERSION: v0.33.11 11 | GO_VERSION: go1.12.8 12 | NODE_VERSION: 10.13.0 13 | 14 | steps: 15 | - checkout 16 | 17 | - run: | 18 | echo 'export NODE_PATH="$HOME/.node_libraries:$NODE_PATH"' >> $BASH_ENV 19 | echo 'export GO111MODULE=on' >> $BASH_ENV 20 | echo 'export PATH="$PWD/node_modules/.bin:$PATH"' >> $BASH_ENV 21 | git --version 22 | 23 | - run: | 24 | # Install nvm. 25 | git clone https://github.com/creationix/nvm.git $HOME/.nvm 26 | cd $HOME/.nvm && git checkout $NVM_VERSION 27 | echo 'export NVM_DIR="$HOME/.nvm"' >> $BASH_ENV 28 | echo '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' >> $BASH_ENV 29 | 30 | - run: | 31 | # Install our own local Go version; we need src/path/filepath to be writable for certain tests. 32 | mkdir $HOME/go 33 | if [[ "$GO_VERSION" =~ go* ]] 34 | then 35 | curl https://storage.googleapis.com/golang/$GO_VERSION.linux-amd64.tar.gz | tar -C $HOME -xz 36 | else 37 | sudo apt-get -y -qq update < /dev/null > /dev/null 38 | sudo apt-get -y -qq install python-pip < /dev/null > /dev/null 39 | pip install -q awscli 40 | export PATH=$HOME/.local/bin:$PATH 41 | aws s3 cp "s3://io.myitcv.gobuilds/linux_amd64/$GO_VERSION.tar.gz" - | tar -C $HOME -xz 42 | fi 43 | chmod a+w $HOME/go/src/path/filepath 44 | echo 'export PATH="$HOME/go/bin:$PATH"' >> $BASH_ENV 45 | 46 | - run: | 47 | # Per https://github.com/gopherjs/gopherjs/pull/687. 48 | echo 'ulimit -s 10000' >> $BASH_ENV 49 | 50 | - run: | 51 | # Setup our required Node version now that nvm is installed. 52 | nvm install $NODE_VERSION node 53 | nvm alias default $NODE_VERSION 54 | echo 'export NODE_PATH="$(npm root --global):$NODE_PATH"' >> $BASH_ENV 55 | 56 | - run: | 57 | # Verify our environment setup. 58 | which node 59 | which go 60 | node --version 61 | go version 62 | go env 63 | 64 | - run: | 65 | # Per https://github.com/gopherjs/gopherjs/blob/master/doc/syscalls.md. 66 | npm install -g node-gyp 67 | cd node-syscall && node-gyp rebuild && mkdir -p $HOME/.node_libraries/ && cp build/Release/syscall.node $HOME/.node_libraries/syscall.node 68 | 69 | npm install -g source-map-support 70 | 71 | # this gives us the repo-local binaries we require 72 | npm install 73 | - run: go install github.com/gopherjs/gopherjs 74 | - run: go generate ./... 75 | - run: go mod tidy 76 | - run: go run genmodstubbs.go 77 | - run: git diff 78 | - run: diff -u <(echo -n) <(git status --porcelain) 79 | - run: diff -u <(echo -n) <(gofmt -d .) 80 | - run: go vet $(go list ./... | grep -v -x -f .vet_exclusions) 81 | - run: diff -u <(echo "github.com/gopherjs/gopherjs/compiler/natives") <(go list ./compiler/natives/...) 82 | - run: gopherjs install -v net/http 83 | - run: gopherjs test --minify -v --short github.com/gopherjs/gopherjs/tests/... $(go list std | grep -v -x -f .std_test_pkg_exclusions) 84 | - run: go test -v ./... 85 | - run: SOURCE_MAP_SUPPORT=false go run tests/run.go -summary 86 | - run: gopherjs test -v fmt 87 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.bin 2 | /node-syscall/build 3 | /node_modules 4 | -------------------------------------------------------------------------------- /.std_test_pkg_exclusions: -------------------------------------------------------------------------------- 1 | context 2 | crypto 3 | crypto/tls 4 | crypto/x509/pkix 5 | debug/gosym 6 | debug/plan9obj 7 | encoding 8 | go/build 9 | go/importer 10 | go/internal/gccgoimporter 11 | go/internal/gcimporter 12 | go/internal/srcimporter 13 | go/types 14 | hash 15 | image/color/palette 16 | image/internal/imageutil 17 | internal/cpu 18 | internal/nettrace 19 | internal/poll 20 | internal/race 21 | internal/singleflight 22 | internal/syscall/unix 23 | internal/syscall/windows 24 | internal/syscall/windows/registry 25 | internal/syscall/windows/sysdll 26 | internal/testenv 27 | internal/testlog 28 | internal/trace 29 | 30 | # GopherJS does not support network access 31 | internal/x/net/nettest 32 | 33 | log 34 | log/syslog 35 | net 36 | net/http 37 | net/http/cgi 38 | net/http/httptest 39 | net/http/httptrace 40 | net/http/httputil 41 | net/http/internal 42 | net/http/pprof 43 | net/internal/socktest 44 | net/rpc 45 | net/smtp 46 | os 47 | os/exec 48 | os/signal 49 | os/signal/internal/pty 50 | os/user 51 | plugin 52 | runtime 53 | runtime/cgo 54 | runtime/debug 55 | runtime/internal/atomic 56 | runtime/internal/sys 57 | runtime/pprof 58 | runtime/pprof/internal/profile 59 | runtime/race 60 | runtime/trace 61 | syscall 62 | testing 63 | testing/internal/testdeps 64 | testing/iotest 65 | unsafe 66 | -------------------------------------------------------------------------------- /.vet_exclusions: -------------------------------------------------------------------------------- 1 | github.com/gopherjs/gopherjs/tests 2 | github.com/gopherjs/gopherjs/tests/syscalljs 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Richard Musiol. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 15 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 16 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 18 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 20 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /compiler/analysis/bool.go: -------------------------------------------------------------------------------- 1 | package analysis 2 | 3 | import ( 4 | "go/ast" 5 | "go/constant" 6 | "go/token" 7 | "go/types" 8 | ) 9 | 10 | func BoolValue(expr ast.Expr, info *types.Info) (bool, bool) { 11 | v := info.Types[expr].Value 12 | if v != nil && v.Kind() == constant.Bool { 13 | return constant.BoolVal(v), true 14 | } 15 | switch e := expr.(type) { 16 | case *ast.BinaryExpr: 17 | switch e.Op { 18 | case token.LAND: 19 | if b, ok := BoolValue(e.X, info); ok { 20 | if !b { 21 | return false, true 22 | } 23 | return BoolValue(e.Y, info) 24 | } 25 | case token.LOR: 26 | if b, ok := BoolValue(e.X, info); ok { 27 | if b { 28 | return true, true 29 | } 30 | return BoolValue(e.Y, info) 31 | } 32 | } 33 | case *ast.UnaryExpr: 34 | if e.Op == token.NOT { 35 | if b, ok := BoolValue(e.X, info); ok { 36 | return !b, true 37 | } 38 | } 39 | case *ast.ParenExpr: 40 | return BoolValue(e.X, info) 41 | } 42 | return false, false 43 | } 44 | -------------------------------------------------------------------------------- /compiler/analysis/break.go: -------------------------------------------------------------------------------- 1 | package analysis 2 | 3 | import ( 4 | "go/ast" 5 | "go/token" 6 | ) 7 | 8 | func HasBreak(n ast.Node) bool { 9 | v := hasBreakVisitor{} 10 | ast.Walk(&v, n) 11 | return v.hasBreak 12 | } 13 | 14 | type hasBreakVisitor struct { 15 | hasBreak bool 16 | } 17 | 18 | func (v *hasBreakVisitor) Visit(node ast.Node) (w ast.Visitor) { 19 | if v.hasBreak { 20 | return nil 21 | } 22 | switch n := node.(type) { 23 | case *ast.BranchStmt: 24 | if n.Tok == token.BREAK && n.Label == nil { 25 | v.hasBreak = true 26 | return nil 27 | } 28 | case *ast.ForStmt, *ast.RangeStmt, *ast.SwitchStmt, *ast.TypeSwitchStmt, *ast.SelectStmt, ast.Expr: 29 | return nil 30 | } 31 | return v 32 | } 33 | -------------------------------------------------------------------------------- /compiler/analysis/escape.go: -------------------------------------------------------------------------------- 1 | package analysis 2 | 3 | import ( 4 | "go/ast" 5 | "go/token" 6 | "go/types" 7 | ) 8 | 9 | func EscapingObjects(n ast.Node, info *types.Info) []*types.Var { 10 | v := escapeAnalysis{ 11 | info: info, 12 | escaping: make(map[*types.Var]bool), 13 | topScope: info.Scopes[n], 14 | bottomScopes: make(map[*types.Scope]bool), 15 | } 16 | ast.Walk(&v, n) 17 | var list []*types.Var 18 | for obj := range v.escaping { 19 | list = append(list, obj) 20 | } 21 | return list 22 | } 23 | 24 | type escapeAnalysis struct { 25 | info *types.Info 26 | escaping map[*types.Var]bool 27 | topScope *types.Scope 28 | bottomScopes map[*types.Scope]bool 29 | } 30 | 31 | func (v *escapeAnalysis) Visit(node ast.Node) (w ast.Visitor) { 32 | // huge overapproximation 33 | switch n := node.(type) { 34 | case *ast.UnaryExpr: 35 | if n.Op == token.AND { 36 | if _, ok := n.X.(*ast.Ident); ok { 37 | return &escapingObjectCollector{v} 38 | } 39 | } 40 | case *ast.FuncLit: 41 | v.bottomScopes[v.info.Scopes[n.Type]] = true 42 | return &escapingObjectCollector{v} 43 | case *ast.ForStmt: 44 | v.bottomScopes[v.info.Scopes[n.Body]] = true 45 | case *ast.RangeStmt: 46 | v.bottomScopes[v.info.Scopes[n.Body]] = true 47 | } 48 | return v 49 | } 50 | 51 | type escapingObjectCollector struct { 52 | analysis *escapeAnalysis 53 | } 54 | 55 | func (v *escapingObjectCollector) Visit(node ast.Node) (w ast.Visitor) { 56 | if id, ok := node.(*ast.Ident); ok { 57 | if obj, ok := v.analysis.info.Uses[id].(*types.Var); ok { 58 | for s := obj.Parent(); s != nil; s = s.Parent() { 59 | if s == v.analysis.topScope { 60 | v.analysis.escaping[obj] = true 61 | break 62 | } 63 | if v.analysis.bottomScopes[s] { 64 | break 65 | } 66 | } 67 | } 68 | } 69 | return v 70 | } 71 | -------------------------------------------------------------------------------- /compiler/analysis/sideeffect.go: -------------------------------------------------------------------------------- 1 | package analysis 2 | 3 | import ( 4 | "go/ast" 5 | "go/token" 6 | "go/types" 7 | ) 8 | 9 | func HasSideEffect(n ast.Node, info *types.Info) bool { 10 | v := hasSideEffectVisitor{info: info} 11 | ast.Walk(&v, n) 12 | return v.hasSideEffect 13 | } 14 | 15 | type hasSideEffectVisitor struct { 16 | info *types.Info 17 | hasSideEffect bool 18 | } 19 | 20 | func (v *hasSideEffectVisitor) Visit(node ast.Node) (w ast.Visitor) { 21 | if v.hasSideEffect { 22 | return nil 23 | } 24 | switch n := node.(type) { 25 | case *ast.CallExpr: 26 | if _, isSig := v.info.TypeOf(n.Fun).(*types.Signature); isSig { // skip conversions 27 | v.hasSideEffect = true 28 | return nil 29 | } 30 | case *ast.UnaryExpr: 31 | if n.Op == token.ARROW { 32 | v.hasSideEffect = true 33 | return nil 34 | } 35 | } 36 | return v 37 | } 38 | -------------------------------------------------------------------------------- /compiler/astutil/astutil.go: -------------------------------------------------------------------------------- 1 | package astutil 2 | 3 | import ( 4 | "go/ast" 5 | "go/types" 6 | ) 7 | 8 | func RemoveParens(e ast.Expr) ast.Expr { 9 | for { 10 | p, isParen := e.(*ast.ParenExpr) 11 | if !isParen { 12 | return e 13 | } 14 | e = p.X 15 | } 16 | } 17 | 18 | func SetType(info *types.Info, t types.Type, e ast.Expr) ast.Expr { 19 | info.Types[e] = types.TypeAndValue{Type: t} 20 | return e 21 | } 22 | 23 | func NewIdent(name string, t types.Type, info *types.Info, pkg *types.Package) *ast.Ident { 24 | ident := ast.NewIdent(name) 25 | info.Types[ident] = types.TypeAndValue{Type: t} 26 | obj := types.NewVar(0, pkg, name, t) 27 | info.Uses[ident] = obj 28 | return ident 29 | } 30 | 31 | func IsTypeExpr(expr ast.Expr, info *types.Info) bool { 32 | switch e := expr.(type) { 33 | case *ast.ArrayType, *ast.ChanType, *ast.FuncType, *ast.InterfaceType, *ast.MapType, *ast.StructType: 34 | return true 35 | case *ast.StarExpr: 36 | return IsTypeExpr(e.X, info) 37 | case *ast.Ident: 38 | _, ok := info.Uses[e].(*types.TypeName) 39 | return ok 40 | case *ast.SelectorExpr: 41 | _, ok := info.Uses[e.Sel].(*types.TypeName) 42 | return ok 43 | case *ast.ParenExpr: 44 | return IsTypeExpr(e.X, info) 45 | default: 46 | return false 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /compiler/filter/assign.go: -------------------------------------------------------------------------------- 1 | package filter 2 | 3 | import ( 4 | "go/ast" 5 | "go/token" 6 | "go/types" 7 | 8 | "github.com/gopherjs/gopherjs/compiler/astutil" 9 | ) 10 | 11 | func Assign(stmt ast.Stmt, info *types.Info, pkg *types.Package) ast.Stmt { 12 | if s, ok := stmt.(*ast.AssignStmt); ok && s.Tok != token.ASSIGN && s.Tok != token.DEFINE { 13 | var op token.Token 14 | switch s.Tok { 15 | case token.ADD_ASSIGN: 16 | op = token.ADD 17 | case token.SUB_ASSIGN: 18 | op = token.SUB 19 | case token.MUL_ASSIGN: 20 | op = token.MUL 21 | case token.QUO_ASSIGN: 22 | op = token.QUO 23 | case token.REM_ASSIGN: 24 | op = token.REM 25 | case token.AND_ASSIGN: 26 | op = token.AND 27 | case token.OR_ASSIGN: 28 | op = token.OR 29 | case token.XOR_ASSIGN: 30 | op = token.XOR 31 | case token.SHL_ASSIGN: 32 | op = token.SHL 33 | case token.SHR_ASSIGN: 34 | op = token.SHR 35 | case token.AND_NOT_ASSIGN: 36 | op = token.AND_NOT 37 | default: 38 | panic(s.Tok) 39 | } 40 | 41 | var list []ast.Stmt 42 | 43 | var viaTmpVars func(expr ast.Expr, name string) ast.Expr 44 | viaTmpVars = func(expr ast.Expr, name string) ast.Expr { 45 | switch e := astutil.RemoveParens(expr).(type) { 46 | case *ast.IndexExpr: 47 | return astutil.SetType(info, info.TypeOf(e), &ast.IndexExpr{ 48 | X: viaTmpVars(e.X, "_slice"), 49 | Index: viaTmpVars(e.Index, "_index"), 50 | }) 51 | 52 | case *ast.SelectorExpr: 53 | sel, ok := info.Selections[e] 54 | if !ok { 55 | // qualified identifier 56 | return e 57 | } 58 | newSel := &ast.SelectorExpr{ 59 | X: viaTmpVars(e.X, "_struct"), 60 | Sel: e.Sel, 61 | } 62 | info.Selections[newSel] = sel 63 | return astutil.SetType(info, info.TypeOf(e), newSel) 64 | 65 | case *ast.StarExpr: 66 | return astutil.SetType(info, info.TypeOf(e), &ast.StarExpr{ 67 | X: viaTmpVars(e.X, "_ptr"), 68 | }) 69 | 70 | case *ast.Ident, *ast.BasicLit: 71 | return e 72 | 73 | default: 74 | tmpVar := astutil.NewIdent(name, info.TypeOf(e), info, pkg) 75 | list = append(list, &ast.AssignStmt{ 76 | Lhs: []ast.Expr{tmpVar}, 77 | Tok: token.DEFINE, 78 | Rhs: []ast.Expr{e}, 79 | }) 80 | return tmpVar 81 | 82 | } 83 | } 84 | 85 | lhs := viaTmpVars(s.Lhs[0], "_val") 86 | 87 | list = append(list, &ast.AssignStmt{ 88 | Lhs: []ast.Expr{lhs}, 89 | Tok: token.ASSIGN, 90 | Rhs: []ast.Expr{ 91 | astutil.SetType(info, info.TypeOf(s.Lhs[0]), &ast.BinaryExpr{ 92 | X: lhs, 93 | Op: op, 94 | Y: astutil.SetType(info, info.TypeOf(s.Rhs[0]), &ast.ParenExpr{ 95 | X: s.Rhs[0], 96 | }), 97 | }), 98 | }, 99 | }) 100 | 101 | return &ast.BlockStmt{ 102 | List: list, 103 | } 104 | } 105 | return stmt 106 | } 107 | -------------------------------------------------------------------------------- /compiler/filter/incdecstmt.go: -------------------------------------------------------------------------------- 1 | package filter 2 | 3 | import ( 4 | "go/ast" 5 | "go/constant" 6 | "go/token" 7 | "go/types" 8 | ) 9 | 10 | func IncDecStmt(stmt ast.Stmt, info *types.Info) ast.Stmt { 11 | if s, ok := stmt.(*ast.IncDecStmt); ok { 12 | t := info.TypeOf(s.X) 13 | if iExpr, isIExpr := s.X.(*ast.IndexExpr); isIExpr { 14 | switch u := info.TypeOf(iExpr.X).Underlying().(type) { 15 | case *types.Array: 16 | t = u.Elem() 17 | case *types.Slice: 18 | t = u.Elem() 19 | case *types.Map: 20 | t = u.Elem() 21 | } 22 | } 23 | 24 | tok := token.ADD_ASSIGN 25 | if s.Tok == token.DEC { 26 | tok = token.SUB_ASSIGN 27 | } 28 | 29 | one := &ast.BasicLit{Kind: token.INT} 30 | info.Types[one] = types.TypeAndValue{Type: t, Value: constant.MakeInt64(1)} 31 | 32 | return &ast.AssignStmt{ 33 | Lhs: []ast.Expr{s.X}, 34 | Tok: tok, 35 | Rhs: []ast.Expr{one}, 36 | } 37 | } 38 | return stmt 39 | } 40 | -------------------------------------------------------------------------------- /compiler/gopherjspkg/doc.go: -------------------------------------------------------------------------------- 1 | // Package gopherjspkg provides core GopherJS packages via a virtual filesystem. 2 | // 3 | // Core GopherJS packages are packages that are critical for GopherJS compiler 4 | // operation. They are needed to build the Go standard library with GopherJS. 5 | // Currently, they include: 6 | // 7 | // github.com/gopherjs/gopherjs/js 8 | // github.com/gopherjs/gopherjs/nosync 9 | // 10 | package gopherjspkg 11 | 12 | //go:generate go run github.com/shurcooL/vfsgen/cmd/vfsgendev -source="github.com/gopherjs/gopherjs/compiler/gopherjspkg".FS -tag=gopherjsdev -nomodtime 13 | -------------------------------------------------------------------------------- /compiler/gopherjspkg/fs.go: -------------------------------------------------------------------------------- 1 | // +build gopherjsdev 2 | 3 | package gopherjspkg 4 | 5 | import ( 6 | "go/build" 7 | "log" 8 | "net/http" 9 | "os" 10 | pathpkg "path" 11 | 12 | "github.com/shurcooL/httpfs/filter" 13 | ) 14 | 15 | // FS is a virtual filesystem that contains core GopherJS packages. 16 | var FS = filter.Keep( 17 | http.Dir(importPathToDir("github.com/gopherjs/gopherjs")), 18 | func(path string, fi os.FileInfo) bool { 19 | return path == "/" || 20 | path == "/js" || (pathpkg.Dir(path) == "/js" && !fi.IsDir()) || 21 | path == "/nosync" || (pathpkg.Dir(path) == "/nosync" && !fi.IsDir()) 22 | }, 23 | ) 24 | 25 | func importPathToDir(importPath string) string { 26 | p, err := build.Import(importPath, ".", build.FindOnly) 27 | if err != nil { 28 | log.Fatalln(err) 29 | } 30 | return p.Dir 31 | } 32 | -------------------------------------------------------------------------------- /compiler/natives/doc.go: -------------------------------------------------------------------------------- 1 | // Package natives provides native packages via a virtual filesystem. 2 | // 3 | // See documentation of parseAndAugment in github.com/gopherjs/gopherjs/build 4 | // for explanation of behavior used to augment the native packages using the files 5 | // in src subfolder. 6 | package natives 7 | 8 | //go:generate go run github.com/shurcooL/vfsgen/cmd/vfsgendev -source="github.com/gopherjs/gopherjs/compiler/natives".FS -tag=gopherjsdev -nomodtime 9 | -------------------------------------------------------------------------------- /compiler/natives/fs.go: -------------------------------------------------------------------------------- 1 | // +build gopherjsdev 2 | 3 | package natives 4 | 5 | import ( 6 | "go/build" 7 | "log" 8 | "net/http" 9 | "os" 10 | "strings" 11 | 12 | "github.com/shurcooL/httpfs/filter" 13 | ) 14 | 15 | // FS is a virtual filesystem that contains native packages. 16 | var FS = filter.Keep( 17 | http.Dir(importPathToDir("github.com/gopherjs/gopherjs/compiler/natives")), 18 | func(path string, fi os.FileInfo) bool { 19 | return path == "/" || path == "/src" || strings.HasPrefix(path, "/src/") 20 | }, 21 | ) 22 | 23 | func importPathToDir(importPath string) string { 24 | p, err := build.Import(importPath, ".", build.FindOnly) 25 | if err != nil { 26 | log.Fatalln(err) 27 | } 28 | return p.Dir 29 | } 30 | -------------------------------------------------------------------------------- /compiler/natives/src/bytes/bytes.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package bytes 4 | 5 | func IndexByte(s []byte, c byte) int { 6 | for i, b := range s { 7 | if b == c { 8 | return i 9 | } 10 | } 11 | return -1 12 | } 13 | 14 | func Equal(a, b []byte) bool { 15 | if len(a) != len(b) { 16 | return false 17 | } 18 | for i, c := range a { 19 | if c != b[i] { 20 | return false 21 | } 22 | } 23 | return true 24 | } 25 | 26 | func Compare(a, b []byte) int { 27 | for i, ca := range a { 28 | if i >= len(b) { 29 | return 1 30 | } 31 | cb := b[i] 32 | if ca < cb { 33 | return -1 34 | } 35 | if ca > cb { 36 | return 1 37 | } 38 | } 39 | if len(a) < len(b) { 40 | return -1 41 | } 42 | return 0 43 | } 44 | -------------------------------------------------------------------------------- /compiler/natives/src/bytes/bytes_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package bytes_test 4 | 5 | import ( 6 | "testing" 7 | ) 8 | 9 | func dangerousSlice(t *testing.T) []byte { 10 | t.Skip("dangerousSlice relies on syscall.Getpagesize, which GopherJS doesn't implement") 11 | 12 | panic("unreachable") 13 | } 14 | -------------------------------------------------------------------------------- /compiler/natives/src/crypto/internal/subtle/aliasing.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package subtle 4 | 5 | import "github.com/gopherjs/gopherjs/js" 6 | 7 | // AnyOverlap reports whether x and y share memory at any (not necessarily 8 | // corresponding) index. The memory beyond the slice length is ignored. 9 | func AnyOverlap(x, y []byte) bool { 10 | // GopherJS: We can't rely on pointer arithmetic, so use GopherJS slice internals. 11 | return len(x) > 0 && len(y) > 0 && 12 | js.InternalObject(x).Get("$array") == js.InternalObject(y).Get("$array") && 13 | js.InternalObject(x).Get("$offset").Int() <= js.InternalObject(y).Get("$offset").Int()+len(y)-1 && 14 | js.InternalObject(y).Get("$offset").Int() <= js.InternalObject(x).Get("$offset").Int()+len(x)-1 15 | } 16 | -------------------------------------------------------------------------------- /compiler/natives/src/crypto/rand/rand.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package rand 4 | 5 | import ( 6 | "errors" 7 | 8 | "github.com/gopherjs/gopherjs/js" 9 | ) 10 | 11 | func init() { 12 | Reader = &rngReader{} 13 | } 14 | 15 | type rngReader struct{} 16 | 17 | func (r *rngReader) Read(b []byte) (n int, err error) { 18 | array := js.InternalObject(b).Get("$array") 19 | offset := js.InternalObject(b).Get("$offset").Int() 20 | 21 | // browser 22 | crypto := js.Global.Get("crypto") 23 | if crypto == js.Undefined { 24 | crypto = js.Global.Get("msCrypto") 25 | } 26 | if crypto != js.Undefined { 27 | if crypto.Get("getRandomValues") != js.Undefined { 28 | n = len(b) 29 | if n > 65536 { 30 | // Avoid QuotaExceededError thrown by getRandomValues 31 | // when length is more than 65536, as specified in 32 | // http://www.w3.org/TR/WebCryptoAPI/#Crypto-method-getRandomValues 33 | n = 65536 34 | } 35 | crypto.Call("getRandomValues", array.Call("subarray", offset, offset+n)) 36 | return n, nil 37 | } 38 | } 39 | 40 | // Node.js 41 | if require := js.Global.Get("require"); require != js.Undefined { 42 | if randomBytes := require.Invoke("crypto").Get("randomBytes"); randomBytes != js.Undefined { 43 | array.Call("set", randomBytes.Invoke(len(b)), offset) 44 | return len(b), nil 45 | } 46 | } 47 | 48 | return 0, errors.New("crypto/rand not available in this environment") 49 | } 50 | 51 | func batched(f func([]byte) bool, readMax int) func([]byte) bool { 52 | return func(buf []byte) bool { 53 | for len(buf) > readMax { 54 | if !f(buf[:readMax]) { 55 | return false 56 | } 57 | buf = buf[readMax:] 58 | } 59 | return len(buf) == 0 || f(buf) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /compiler/natives/src/crypto/x509/x509.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package x509 4 | 5 | import "errors" 6 | 7 | func loadSystemRoots() (*CertPool, error) { 8 | return nil, errors.New("crypto/x509: system root pool is not available in GopherJS") 9 | } 10 | -------------------------------------------------------------------------------- /compiler/natives/src/crypto/x509/x509_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package x509 4 | 5 | import "testing" 6 | 7 | func TestSystemCertPool(t *testing.T) { 8 | t.Skip("no system roots") 9 | } 10 | 11 | func TestSystemRoots(t *testing.T) { 12 | t.Skip("no system roots") 13 | } 14 | 15 | func TestEnvVars(t *testing.T) { 16 | t.Skip("no system roots") 17 | } 18 | 19 | func TestSystemVerify(t *testing.T) { 20 | t.Skip("no system") 21 | } 22 | 23 | func TestImports(t *testing.T) { 24 | t.Skip("no system") 25 | } 26 | -------------------------------------------------------------------------------- /compiler/natives/src/database/sql/driver/driver_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package driver 4 | 5 | var valueConverterTests = []valueConverterTest{ 6 | {Bool, "true", true, ""}, 7 | {Bool, "True", true, ""}, 8 | {Bool, []byte("t"), true, ""}, 9 | {Bool, true, true, ""}, 10 | {Bool, "1", true, ""}, 11 | {Bool, 1, true, ""}, 12 | {Bool, int64(1), true, ""}, 13 | {Bool, uint16(1), true, ""}, 14 | {Bool, "false", false, ""}, 15 | {Bool, false, false, ""}, 16 | {Bool, "0", false, ""}, 17 | {Bool, 0, false, ""}, 18 | {Bool, int64(0), false, ""}, 19 | {Bool, uint16(0), false, ""}, 20 | {c: Bool, in: "foo", err: "sql/driver: couldn't convert \"foo\" into type bool"}, 21 | {c: Bool, in: 2, err: "sql/driver: couldn't convert 2 into type bool"}, 22 | {DefaultParameterConverter, now, now, ""}, 23 | {DefaultParameterConverter, (*int64)(nil), nil, ""}, 24 | {DefaultParameterConverter, &answer, answer, ""}, 25 | {DefaultParameterConverter, &now, now, ""}, 26 | //{DefaultParameterConverter, i(9), int64(9), ""}, // TODO: Fix. 27 | {DefaultParameterConverter, f(0.1), float64(0.1), ""}, 28 | {DefaultParameterConverter, b(true), true, ""}, 29 | //{DefaultParameterConverter, bs{1}, []byte{1}, ""}, // TODO: Fix. 30 | {DefaultParameterConverter, s("a"), "a", ""}, 31 | {DefaultParameterConverter, is{1}, nil, "unsupported type driver.is, a slice of int"}, 32 | } 33 | -------------------------------------------------------------------------------- /compiler/natives/src/debug/elf/elf_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package elf 4 | 5 | import "testing" 6 | 7 | func TestNoSectionOverlaps(t *testing.T) { 8 | t.Skip("not 6l") 9 | } 10 | -------------------------------------------------------------------------------- /compiler/natives/src/encoding/gob/gob_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package gob 4 | 5 | import ( 6 | "bytes" 7 | "reflect" 8 | "testing" 9 | ) 10 | 11 | // TODO: TestEndToEnd override can be removed once the bug with Marr field is fixed. 12 | func TestEndToEnd(t *testing.T) { 13 | type T2 struct { 14 | T string 15 | } 16 | type T3 struct { 17 | X float64 18 | Z *int 19 | } 20 | type T1 struct { 21 | A, B, C int 22 | M map[string]*float64 23 | M2 map[int]T3 24 | Mstring map[string]string 25 | Mintptr map[int]*int 26 | Mcomp map[complex128]complex128 27 | Marr map[[2]string][2]*float64 28 | EmptyMap map[string]int // to check that we receive a non-nil map. 29 | N *[3]float64 30 | Strs *[2]string 31 | Int64s *[]int64 32 | RI complex64 33 | S string 34 | Y []byte 35 | T *T2 36 | } 37 | pi := 3.14159 38 | e := 2.71828 39 | two := 2.0 40 | meaning := 42 41 | fingers := 5 42 | s1 := "string1" 43 | s2 := "string2" 44 | var comp1 complex128 = complex(1.0, 1.0) 45 | var comp2 complex128 = complex(1.0, 1.0) 46 | var arr1 [2]string 47 | arr1[0] = s1 48 | arr1[1] = s2 49 | var arr2 [2]string 50 | arr2[0] = s2 51 | arr2[1] = s1 52 | var floatArr1 [2]*float64 53 | floatArr1[0] = &pi 54 | floatArr1[1] = &e 55 | var floatArr2 [2]*float64 56 | floatArr2[0] = &e 57 | floatArr2[1] = &two 58 | t1 := &T1{ 59 | A: 17, 60 | B: 18, 61 | C: -5, 62 | M: map[string]*float64{"pi": &pi, "e": &e}, 63 | M2: map[int]T3{4: T3{X: pi, Z: &meaning}, 10: T3{X: e, Z: &fingers}}, 64 | Mstring: map[string]string{"pi": "3.14", "e": "2.71"}, 65 | Mintptr: map[int]*int{meaning: &fingers, fingers: &meaning}, 66 | Mcomp: map[complex128]complex128{comp1: comp2, comp2: comp1}, 67 | // TODO: Fix this problem: 68 | // TypeError: dst.$set is not a function 69 | // at typedmemmove (/github.com/gopherjs/gopherjs/reflect.go:487:3) 70 | //Marr: map[[2]string][2]*float64{arr1: floatArr1, arr2: floatArr2}, 71 | EmptyMap: make(map[string]int), 72 | N: &[3]float64{1.5, 2.5, 3.5}, 73 | Strs: &[2]string{s1, s2}, 74 | Int64s: &[]int64{77, 89, 123412342134}, 75 | RI: 17 - 23i, 76 | S: "Now is the time", 77 | Y: []byte("hello, sailor"), 78 | T: &T2{"this is T2"}, 79 | } 80 | b := new(bytes.Buffer) 81 | err := NewEncoder(b).Encode(t1) 82 | if err != nil { 83 | t.Error("encode:", err) 84 | } 85 | var _t1 T1 86 | err = NewDecoder(b).Decode(&_t1) 87 | if err != nil { 88 | t.Fatal("decode:", err) 89 | } 90 | if !reflect.DeepEqual(t1, &_t1) { 91 | t.Errorf("encode expected %v got %v", *t1, _t1) 92 | } 93 | // Be absolutely sure the received map is non-nil. 94 | if t1.EmptyMap == nil { 95 | t.Errorf("nil map sent") 96 | } 97 | if _t1.EmptyMap == nil { 98 | t.Errorf("nil map received") 99 | } 100 | } 101 | 102 | func TestTypeRace(t *testing.T) { 103 | // encoding/gob currently uses nosync. This test uses sync.WaitGroup and 104 | // cannot succeed when nosync is used. 105 | t.Skip("using nosync") 106 | } 107 | -------------------------------------------------------------------------------- /compiler/natives/src/encoding/json/stream_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package json 4 | 5 | import "testing" 6 | 7 | func TestHTTPDecoding(t *testing.T) { 8 | t.Skip("network access is not supported by GopherJS") 9 | } 10 | -------------------------------------------------------------------------------- /compiler/natives/src/fmt/fmt_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package fmt_test 4 | 5 | const intCount = 100 6 | -------------------------------------------------------------------------------- /compiler/natives/src/go/token/token_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package token 4 | 5 | import ( 6 | "testing" 7 | ) 8 | 9 | func TestFileSetRace(t *testing.T) { 10 | t.Skip() 11 | } 12 | -------------------------------------------------------------------------------- /compiler/natives/src/internal/bytealg/bytealg.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package bytealg 4 | 5 | func Equal(a, b []byte) bool { 6 | if len(a) != len(b) { 7 | return false 8 | } 9 | for i, c := range a { 10 | if c != b[i] { 11 | return false 12 | } 13 | } 14 | return true 15 | } 16 | -------------------------------------------------------------------------------- /compiler/natives/src/internal/cpu/cpu.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package cpu 4 | 5 | const CacheLineSize = 0 6 | const CacheLinePadSize = 0 7 | -------------------------------------------------------------------------------- /compiler/natives/src/internal/fmtsort/fmtsort_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package fmtsort_test 4 | 5 | import ( 6 | "math" 7 | "reflect" 8 | "testing" 9 | 10 | "internal/fmtsort" 11 | ) 12 | 13 | // needsSkip reports whether the kind doesn't work for sorting on GopherJS. 14 | func needsSkip(k reflect.Kind) bool { 15 | switch k { 16 | case reflect.Ptr, reflect.Chan: 17 | return true 18 | } 19 | return false 20 | } 21 | 22 | // Note: sync with the original TestCompare. 23 | func TestCompare(t *testing.T) { 24 | for _, test := range compareTests { 25 | for i, v0 := range test { 26 | for j, v1 := range test { 27 | // GopherJS specific kind check 28 | if needsSkip(v0.Kind()) || needsSkip(v1.Kind()) { 29 | continue 30 | } 31 | 32 | c := fmtsort.Compare(v0, v1) 33 | var expect int 34 | switch { 35 | case i == j: 36 | expect = 0 37 | // NaNs are tricky. 38 | if typ := v0.Type(); (typ.Kind() == reflect.Float32 || typ.Kind() == reflect.Float64) && math.IsNaN(v0.Float()) { 39 | expect = -1 40 | } 41 | case i < j: 42 | expect = -1 43 | case i > j: 44 | expect = 1 45 | } 46 | if c != expect { 47 | t.Errorf("%s: compare(%v,%v)=%d; expect %d", v0.Type(), v0, v1, c, expect) 48 | } 49 | } 50 | } 51 | } 52 | } 53 | 54 | func TestOrder(t *testing.T) { 55 | for _, test := range sortTests { 56 | switch test.data.(type) { 57 | case map[*int]string, map[chan int]string: 58 | // GopherJS doesn't support comparison/ordering of such 59 | // types, unlike "native" architectures 60 | continue 61 | case map[[2]int]string: 62 | // A case of https://github.com/gopherjs/gopherjs/issues/773 63 | continue 64 | } 65 | got := sprint(test.data) 66 | if got != test.print { 67 | t.Errorf("%s: got %q, want %q", reflect.TypeOf(test.data), got, test.print) 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /compiler/natives/src/internal/poll/fd_poll.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package poll 4 | 5 | import "time" 6 | 7 | // pollDesc is a no-op implementation of an I/O poller for GOARCH=js. 8 | // 9 | // Its implementation is based on NaCL in gc compiler (see GOROOT/src/internal/poll/fd_poll_nacl.go), 10 | // but it does even less. 11 | type pollDesc struct { 12 | closing bool 13 | } 14 | 15 | func (pd *pollDesc) init(fd *FD) error { return nil } 16 | 17 | func (pd *pollDesc) close() {} 18 | 19 | func (pd *pollDesc) evict() { pd.closing = true } 20 | 21 | func (pd *pollDesc) prepare(mode int, isFile bool) error { 22 | if pd.closing { 23 | return errClosing(isFile) 24 | } 25 | return nil 26 | } 27 | 28 | func (pd *pollDesc) prepareRead(isFile bool) error { return pd.prepare('r', isFile) } 29 | 30 | func (pd *pollDesc) prepareWrite(isFile bool) error { return pd.prepare('w', isFile) } 31 | 32 | func (pd *pollDesc) wait(mode int, isFile bool) error { 33 | if pd.closing { 34 | return errClosing(isFile) 35 | } 36 | return ErrTimeout 37 | } 38 | 39 | func (pd *pollDesc) waitRead(isFile bool) error { return pd.wait('r', isFile) } 40 | 41 | func (pd *pollDesc) waitWrite(isFile bool) error { return pd.wait('w', isFile) } 42 | 43 | func (*pollDesc) waitCanceled(mode int) {} 44 | 45 | func (*pollDesc) pollable() bool { return true } 46 | 47 | func (*FD) SetDeadline(t time.Time) error { return nil } 48 | 49 | func (*FD) SetReadDeadline(t time.Time) error { return nil } 50 | 51 | func (*FD) SetWriteDeadline(t time.Time) error { return nil } 52 | 53 | // PollDescriptor returns the descriptor being used by the poller, 54 | // or ^uintptr(0) if there isn't one. This is only used for testing. 55 | func PollDescriptor() uintptr { 56 | return ^uintptr(0) 57 | } 58 | 59 | // Copy of sync.runtime_Semacquire. 60 | func runtime_Semacquire(s *uint32) { 61 | if *s == 0 { 62 | ch := make(chan bool) 63 | semWaiters[s] = append(semWaiters[s], ch) 64 | <-ch 65 | } 66 | *s-- 67 | } 68 | 69 | // Copy of sync.runtime_Semrelease. 70 | func runtime_Semrelease(s *uint32) { 71 | *s++ 72 | 73 | w := semWaiters[s] 74 | if len(w) == 0 { 75 | return 76 | } 77 | 78 | ch := w[0] 79 | w = w[1:] 80 | semWaiters[s] = w 81 | if len(w) == 0 { 82 | delete(semWaiters, s) 83 | } 84 | 85 | ch <- true 86 | } 87 | 88 | var semWaiters = make(map[*uint32][]chan bool) 89 | -------------------------------------------------------------------------------- /compiler/natives/src/internal/syscall/unix/unix.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package unix 4 | 5 | const randomTrap = 0 6 | const fstatatTrap = 0 7 | 8 | func IsNonblock(fd int) (nonblocking bool, err error) { 9 | return false, nil 10 | } 11 | -------------------------------------------------------------------------------- /compiler/natives/src/internal/testenv/testenv.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package testenv 4 | 5 | import ( 6 | "runtime" 7 | "strings" 8 | ) 9 | 10 | // HasExec reports whether the current system can start new processes 11 | // using os.StartProcess or (more commonly) exec.Command. 12 | func HasExec() bool { 13 | switch runtime.GOOS { 14 | case "nacl": 15 | return false 16 | case "darwin": 17 | if strings.HasPrefix(runtime.GOARCH, "arm") { 18 | return false 19 | } 20 | } 21 | switch runtime.GOARCH { 22 | case "js": 23 | return false 24 | } 25 | return true 26 | } 27 | -------------------------------------------------------------------------------- /compiler/natives/src/io/io_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package io_test 4 | 5 | import ( 6 | "testing" 7 | ) 8 | 9 | func TestMultiWriter_WriteStringSingleAlloc(t *testing.T) { 10 | t.Skip() 11 | } 12 | 13 | func TestMultiReaderFlatten(t *testing.T) { 14 | t.Skip("test relies on runtime.Callers and runtime.CallersFrames, which GopherJS doesn't support") 15 | } 16 | 17 | func TestMultiWriterSingleChainFlatten(t *testing.T) { 18 | t.Skip("test relies on runtime.Callers and runtime.CallersFrames, which GopherJS doesn't support") 19 | } 20 | 21 | func TestMultiReaderFreesExhaustedReaders(t *testing.T) { 22 | t.Skip("test relies on runtime.SetFinalizer, which GopherJS does not implement") 23 | } 24 | -------------------------------------------------------------------------------- /compiler/natives/src/math/big/big.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package big 4 | 5 | // TODO: This is a workaround for https://github.com/gopherjs/gopherjs/issues/652. 6 | // Remove after that issue is resolved. 7 | type Word uintptr 8 | -------------------------------------------------------------------------------- /compiler/natives/src/math/big/big_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package big 4 | 5 | import "testing" 6 | 7 | func TestBytes(t *testing.T) { 8 | t.Skip("broken") 9 | } 10 | 11 | func TestModSqrt(t *testing.T) { 12 | t.Skip("slow") 13 | } 14 | -------------------------------------------------------------------------------- /compiler/natives/src/math/bits/bits.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package bits 4 | 5 | type _err string 6 | 7 | func (e _err) Error() string { 8 | return string(e) 9 | } 10 | 11 | // RuntimeError implements runtime.Error. 12 | func (e _err) RuntimeError() { 13 | } 14 | 15 | var ( 16 | overflowError error = _err("runtime error: integer overflow") 17 | divideError error = _err("runtime error: integer divide by zero") 18 | ) 19 | -------------------------------------------------------------------------------- /compiler/natives/src/math/math.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package math 4 | 5 | import ( 6 | "github.com/gopherjs/gopherjs/js" 7 | ) 8 | 9 | var math = js.Global.Get("Math") 10 | var zero float64 = 0 11 | var posInf = 1 / zero 12 | var negInf = -1 / zero 13 | var nan = 0 / zero 14 | 15 | func Acos(x float64) float64 { 16 | return math.Call("acos", x).Float() 17 | } 18 | 19 | func Acosh(x float64) float64 { 20 | return math.Call("acosh", x).Float() 21 | } 22 | 23 | func Asin(x float64) float64 { 24 | return math.Call("asin", x).Float() 25 | } 26 | 27 | func Asinh(x float64) float64 { 28 | return math.Call("asinh", x).Float() 29 | } 30 | 31 | func Atan(x float64) float64 { 32 | return math.Call("atan", x).Float() 33 | } 34 | 35 | func Atanh(x float64) float64 { 36 | return math.Call("atanh", x).Float() 37 | } 38 | 39 | func Atan2(y, x float64) float64 { 40 | return math.Call("atan2", y, x).Float() 41 | } 42 | 43 | func Cbrt(x float64) float64 { 44 | return math.Call("cbrt", x).Float() 45 | } 46 | 47 | func Ceil(x float64) float64 { 48 | return math.Call("ceil", x).Float() 49 | } 50 | 51 | func Copysign(x, y float64) float64 { 52 | if (x < 0 || 1/x == negInf) != (y < 0 || 1/y == negInf) { 53 | return -x 54 | } 55 | return x 56 | } 57 | 58 | func Cos(x float64) float64 { 59 | return math.Call("cos", x).Float() 60 | } 61 | 62 | func Cosh(x float64) float64 { 63 | return math.Call("cosh", x).Float() 64 | } 65 | 66 | func Erf(x float64) float64 { 67 | return erf(x) 68 | } 69 | 70 | func Erfc(x float64) float64 { 71 | return erfc(x) 72 | } 73 | 74 | func Exp(x float64) float64 { 75 | return math.Call("exp", x).Float() 76 | } 77 | 78 | func Exp2(x float64) float64 { 79 | return math.Call("pow", 2, x).Float() 80 | } 81 | 82 | func Expm1(x float64) float64 { 83 | return expm1(x) 84 | } 85 | 86 | func Floor(x float64) float64 { 87 | return math.Call("floor", x).Float() 88 | } 89 | 90 | func Frexp(f float64) (frac float64, exp int) { 91 | return frexp(f) 92 | } 93 | 94 | func Hypot(p, q float64) float64 { 95 | return hypot(p, q) 96 | } 97 | 98 | func Inf(sign int) float64 { 99 | switch { 100 | case sign >= 0: 101 | return posInf 102 | default: 103 | return negInf 104 | } 105 | } 106 | 107 | func IsInf(f float64, sign int) bool { 108 | if f == posInf { 109 | return sign >= 0 110 | } 111 | if f == negInf { 112 | return sign <= 0 113 | } 114 | return false 115 | } 116 | 117 | func IsNaN(f float64) (is bool) { 118 | return f != f 119 | } 120 | 121 | func Ldexp(frac float64, exp int) float64 { 122 | if -1024 < exp && exp < 1024 { // Use Math.pow for small exp values where it's viable. For performance. 123 | if frac == 0 { 124 | return frac 125 | } 126 | return frac * math.Call("pow", 2, exp).Float() 127 | } 128 | return ldexp(frac, exp) 129 | } 130 | 131 | func Log(x float64) float64 { 132 | if x != x { // workaround for optimizer bug in V8, remove at some point 133 | return nan 134 | } 135 | return math.Call("log", x).Float() 136 | } 137 | 138 | func Log10(x float64) float64 { 139 | return log10(x) 140 | } 141 | 142 | func Log1p(x float64) float64 { 143 | return log1p(x) 144 | } 145 | 146 | func Log2(x float64) float64 { 147 | return log2(x) 148 | } 149 | 150 | func Max(x, y float64) float64 { 151 | return max(x, y) 152 | } 153 | 154 | func Min(x, y float64) float64 { 155 | return min(x, y) 156 | } 157 | 158 | func Mod(x, y float64) float64 { 159 | return js.Global.Call("$mod", x, y).Float() 160 | } 161 | 162 | func Modf(f float64) (float64, float64) { 163 | if f == posInf || f == negInf { 164 | return f, nan 165 | } 166 | if 1/f == negInf { 167 | return f, f 168 | } 169 | frac := Mod(f, 1) 170 | return f - frac, frac 171 | } 172 | 173 | func NaN() float64 { 174 | return nan 175 | } 176 | 177 | func Pow(x, y float64) float64 { 178 | if x == 1 || (x == -1 && (y == posInf || y == negInf)) { 179 | return 1 180 | } 181 | return math.Call("pow", x, y).Float() 182 | } 183 | 184 | func Remainder(x, y float64) float64 { 185 | return remainder(x, y) 186 | } 187 | 188 | func Signbit(x float64) bool { 189 | return x < 0 || 1/x == negInf 190 | } 191 | 192 | func Sin(x float64) float64 { 193 | return math.Call("sin", x).Float() 194 | } 195 | 196 | func Sinh(x float64) float64 { 197 | return math.Call("sinh", x).Float() 198 | } 199 | 200 | func Sincos(x float64) (sin, cos float64) { 201 | return Sin(x), Cos(x) 202 | } 203 | 204 | func Sqrt(x float64) float64 { 205 | return math.Call("sqrt", x).Float() 206 | } 207 | 208 | func Tan(x float64) float64 { 209 | return math.Call("tan", x).Float() 210 | } 211 | 212 | func Tanh(x float64) float64 { 213 | return math.Call("tanh", x).Float() 214 | } 215 | 216 | func Trunc(x float64) float64 { 217 | if x == posInf || x == negInf || x != x || 1/x == negInf { 218 | return x 219 | } 220 | return Copysign(float64(int(x)), x) 221 | } 222 | 223 | var buf struct { 224 | uint32array [2]uint32 225 | float32array [2]float32 226 | float64array [1]float64 227 | } 228 | 229 | func init() { 230 | ab := js.Global.Get("ArrayBuffer").New(8) 231 | js.InternalObject(buf).Set("uint32array", js.Global.Get("Uint32Array").New(ab)) 232 | js.InternalObject(buf).Set("float32array", js.Global.Get("Float32Array").New(ab)) 233 | js.InternalObject(buf).Set("float64array", js.Global.Get("Float64Array").New(ab)) 234 | } 235 | 236 | func Float32bits(f float32) uint32 { 237 | buf.float32array[0] = f 238 | return buf.uint32array[0] 239 | } 240 | 241 | func Float32frombits(b uint32) float32 { 242 | buf.uint32array[0] = b 243 | return buf.float32array[0] 244 | } 245 | 246 | func Float64bits(f float64) uint64 { 247 | buf.float64array[0] = f 248 | return uint64(buf.uint32array[1])<<32 + uint64(buf.uint32array[0]) 249 | } 250 | 251 | func Float64frombits(b uint64) float64 { 252 | buf.uint32array[0] = uint32(b) 253 | buf.uint32array[1] = uint32(b >> 32) 254 | return buf.float64array[0] 255 | } 256 | -------------------------------------------------------------------------------- /compiler/natives/src/math/math_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package math_test 4 | 5 | import ( 6 | "testing" 7 | ) 8 | 9 | // Slighly higher tolerances than upstream, otherwise TestGamma fails. 10 | // TODO: Is there a better way to fix TestGamma? It's weird that only one test 11 | // requires increasing tolerances. Perhaps there's a better fix? Maybe we 12 | // should override TestGamma specifically and not the package-wide tolerances, 13 | // because this will cause many other tests to be less accurate. Or maybe this 14 | // is fine? 15 | func close(a, b float64) bool { return tolerance(a, b, 4e-14) } 16 | func veryclose(a, b float64) bool { return tolerance(a, b, 6e-15) } 17 | 18 | func testExp(t *testing.T, Exp func(float64) float64, name string) { 19 | t.Skip("inaccurate") 20 | } 21 | -------------------------------------------------------------------------------- /compiler/natives/src/math/rand/rand_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package rand 4 | 5 | import "testing" 6 | 7 | func TestFloat32(t *testing.T) { 8 | t.Skip("slow") 9 | } 10 | 11 | func TestConcurrent(t *testing.T) { 12 | t.Skip("using nosync") 13 | } 14 | -------------------------------------------------------------------------------- /compiler/natives/src/net/http/cookiejar/example_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package cookiejar_test 4 | 5 | import "fmt" 6 | 7 | func ExampleNew() { 8 | // network access not supported by GopherJS, and this test depends on httptest.NewServer 9 | 10 | fmt.Println(`After 1st request: 11 | Flavor: Chocolate Chip 12 | After 2nd request: 13 | Flavor: Oatmeal Raisin`) 14 | } 15 | -------------------------------------------------------------------------------- /compiler/natives/src/net/http/fetch.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package http 4 | 5 | import ( 6 | "errors" 7 | "fmt" 8 | "io" 9 | "io/ioutil" 10 | "strconv" 11 | 12 | "github.com/gopherjs/gopherjs/js" 13 | ) 14 | 15 | // streamReader implements an io.ReadCloser wrapper for ReadableStream of https://fetch.spec.whatwg.org/. 16 | type streamReader struct { 17 | pending []byte 18 | stream *js.Object 19 | } 20 | 21 | func (r *streamReader) Read(p []byte) (n int, err error) { 22 | if len(r.pending) == 0 { 23 | var ( 24 | bCh = make(chan []byte) 25 | errCh = make(chan error) 26 | ) 27 | r.stream.Call("read").Call("then", 28 | func(result *js.Object) { 29 | if result.Get("done").Bool() { 30 | errCh <- io.EOF 31 | return 32 | } 33 | bCh <- result.Get("value").Interface().([]byte) 34 | }, 35 | func(reason *js.Object) { 36 | // Assumes it's a DOMException. 37 | errCh <- errors.New(reason.Get("message").String()) 38 | }, 39 | ) 40 | select { 41 | case b := <-bCh: 42 | r.pending = b 43 | case err := <-errCh: 44 | return 0, err 45 | } 46 | } 47 | n = copy(p, r.pending) 48 | r.pending = r.pending[n:] 49 | return n, nil 50 | } 51 | 52 | func (r *streamReader) Close() error { 53 | // This ignores any error returned from cancel method. So far, I did not encounter any concrete 54 | // situation where reporting the error is meaningful. Most users ignore error from resp.Body.Close(). 55 | // If there's a need to report error here, it can be implemented and tested when that need comes up. 56 | r.stream.Call("cancel") 57 | return nil 58 | } 59 | 60 | // fetchTransport is a RoundTripper that is implemented using Fetch API. It supports streaming 61 | // response bodies. 62 | type fetchTransport struct{} 63 | 64 | func (t *fetchTransport) RoundTrip(req *Request) (*Response, error) { 65 | headers := js.Global.Get("Headers").New() 66 | for key, values := range req.Header { 67 | for _, value := range values { 68 | headers.Call("append", key, value) 69 | } 70 | } 71 | opt := map[string]interface{}{ 72 | "method": req.Method, 73 | "headers": headers, 74 | "credentials": "same-origin", 75 | } 76 | if req.Body != nil { 77 | // TODO: Find out if request body can be streamed into the fetch request rather than in advance here. 78 | // See BufferSource at https://fetch.spec.whatwg.org/#body-mixin. 79 | body, err := ioutil.ReadAll(req.Body) 80 | if err != nil { 81 | req.Body.Close() // RoundTrip must always close the body, including on errors. 82 | return nil, err 83 | } 84 | req.Body.Close() 85 | opt["body"] = body 86 | } 87 | respPromise := js.Global.Call("fetch", req.URL.String(), opt) 88 | 89 | var ( 90 | respCh = make(chan *Response) 91 | errCh = make(chan error) 92 | ) 93 | respPromise.Call("then", 94 | func(result *js.Object) { 95 | header := Header{} 96 | result.Get("headers").Call("forEach", func(value, key *js.Object) { 97 | ck := CanonicalHeaderKey(key.String()) 98 | header[ck] = append(header[ck], value.String()) 99 | }) 100 | 101 | contentLength := int64(-1) 102 | if cl, err := strconv.ParseInt(header.Get("Content-Length"), 10, 64); err == nil { 103 | contentLength = cl 104 | } 105 | 106 | select { 107 | case respCh <- &Response{ 108 | Status: result.Get("status").String() + " " + StatusText(result.Get("status").Int()), 109 | StatusCode: result.Get("status").Int(), 110 | Header: header, 111 | ContentLength: contentLength, 112 | Body: &streamReader{stream: result.Get("body").Call("getReader")}, 113 | Request: req, 114 | }: 115 | case <-req.Context().Done(): 116 | } 117 | }, 118 | func(reason *js.Object) { 119 | select { 120 | case errCh <- fmt.Errorf("net/http: fetch() failed: %s", reason.String()): 121 | case <-req.Context().Done(): 122 | } 123 | }, 124 | ) 125 | select { 126 | case <-req.Context().Done(): 127 | // TODO: Abort request if possible using Fetch API. 128 | return nil, errors.New("net/http: request canceled") 129 | case resp := <-respCh: 130 | return resp, nil 131 | case err := <-errCh: 132 | return nil, err 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /compiler/natives/src/net/http/http.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package http 4 | 5 | import ( 6 | "bufio" 7 | "bytes" 8 | "errors" 9 | "io/ioutil" 10 | "net/textproto" 11 | "strconv" 12 | 13 | "github.com/gopherjs/gopherjs/js" 14 | ) 15 | 16 | var DefaultTransport = func() RoundTripper { 17 | switch { 18 | case js.Global.Get("fetch") != js.Undefined && js.Global.Get("ReadableStream") != js.Undefined: // ReadableStream is used as a check for support of streaming response bodies, see https://fetch.spec.whatwg.org/#streams. 19 | return &fetchTransport{} 20 | case js.Global.Get("XMLHttpRequest") != js.Undefined: 21 | return &XHRTransport{} 22 | default: 23 | return noTransport{} 24 | } 25 | }() 26 | 27 | // noTransport is used when neither Fetch API nor XMLHttpRequest API are available. It always fails. 28 | type noTransport struct{} 29 | 30 | func (noTransport) RoundTrip(req *Request) (*Response, error) { 31 | return nil, errors.New("net/http: neither of Fetch nor XMLHttpRequest APIs is available") 32 | } 33 | 34 | type XHRTransport struct { 35 | inflight map[*Request]*js.Object 36 | } 37 | 38 | func (t *XHRTransport) RoundTrip(req *Request) (*Response, error) { 39 | xhr := js.Global.Get("XMLHttpRequest").New() 40 | 41 | if t.inflight == nil { 42 | t.inflight = map[*Request]*js.Object{} 43 | } 44 | t.inflight[req] = xhr 45 | defer delete(t.inflight, req) 46 | 47 | respCh := make(chan *Response) 48 | errCh := make(chan error) 49 | 50 | xhr.Set("onload", func() { 51 | header, _ := textproto.NewReader(bufio.NewReader(bytes.NewReader([]byte(xhr.Call("getAllResponseHeaders").String() + "\n")))).ReadMIMEHeader() 52 | body := js.Global.Get("Uint8Array").New(xhr.Get("response")).Interface().([]byte) 53 | 54 | contentLength := int64(-1) 55 | switch req.Method { 56 | case "HEAD": 57 | if l, err := strconv.ParseInt(header.Get("Content-Length"), 10, 64); err == nil { 58 | contentLength = l 59 | } 60 | default: 61 | contentLength = int64(len(body)) 62 | } 63 | 64 | respCh <- &Response{ 65 | Status: xhr.Get("status").String() + " " + xhr.Get("statusText").String(), 66 | StatusCode: xhr.Get("status").Int(), 67 | Header: Header(header), 68 | ContentLength: contentLength, 69 | Body: ioutil.NopCloser(bytes.NewReader(body)), 70 | Request: req, 71 | } 72 | }) 73 | 74 | xhr.Set("onerror", func(e *js.Object) { 75 | errCh <- errors.New("net/http: XMLHttpRequest failed") 76 | }) 77 | 78 | xhr.Set("onabort", func(e *js.Object) { 79 | errCh <- errors.New("net/http: request canceled") 80 | }) 81 | 82 | xhr.Call("open", req.Method, req.URL.String()) 83 | xhr.Set("responseType", "arraybuffer") // has to be after "open" until https://bugzilla.mozilla.org/show_bug.cgi?id=1110761 is resolved 84 | for key, values := range req.Header { 85 | for _, value := range values { 86 | xhr.Call("setRequestHeader", key, value) 87 | } 88 | } 89 | if req.Body == nil { 90 | xhr.Call("send") 91 | } else { 92 | body, err := ioutil.ReadAll(req.Body) 93 | if err != nil { 94 | req.Body.Close() // RoundTrip must always close the body, including on errors. 95 | return nil, err 96 | } 97 | req.Body.Close() 98 | xhr.Call("send", body) 99 | } 100 | 101 | select { 102 | case resp := <-respCh: 103 | return resp, nil 104 | case err := <-errCh: 105 | return nil, err 106 | } 107 | } 108 | 109 | func (t *XHRTransport) CancelRequest(req *Request) { 110 | if xhr, ok := t.inflight[req]; ok { 111 | xhr.Call("abort") 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /compiler/natives/src/net/net.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package net 4 | 5 | import ( 6 | "errors" 7 | "syscall" 8 | 9 | "github.com/gopherjs/gopherjs/js" 10 | ) 11 | 12 | func Listen(net, laddr string) (Listener, error) { 13 | panic(errors.New("network access is not supported by GopherJS")) 14 | } 15 | 16 | func (d *Dialer) Dial(network, address string) (Conn, error) { 17 | panic(errors.New("network access is not supported by GopherJS")) 18 | } 19 | 20 | func sysInit() { 21 | } 22 | 23 | func probeIPv4Stack() bool { 24 | return false 25 | } 26 | 27 | func probeIPv6Stack() (supportsIPv6, supportsIPv4map bool) { 28 | return false, false 29 | } 30 | 31 | func probeWindowsIPStack() (supportsVistaIP bool) { 32 | return false 33 | } 34 | 35 | func maxListenerBacklog() int { 36 | return syscall.SOMAXCONN 37 | } 38 | 39 | // Copy of strings.IndexByte. 40 | func byteIndex(s string, c byte) int { 41 | return js.InternalObject(s).Call("indexOf", js.Global.Get("String").Call("fromCharCode", c)).Int() 42 | } 43 | 44 | // Copy of bytes.Equal. 45 | func bytesEqual(x, y []byte) bool { 46 | if len(x) != len(y) { 47 | return false 48 | } 49 | for i, b := range x { 50 | if b != y[i] { 51 | return false 52 | } 53 | } 54 | return true 55 | } 56 | 57 | // Copy of bytes.IndexByte. 58 | func bytesIndexByte(s []byte, c byte) int { 59 | for i, b := range s { 60 | if b == c { 61 | return i 62 | } 63 | } 64 | return -1 65 | } 66 | -------------------------------------------------------------------------------- /compiler/natives/src/os/os.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package os 4 | 5 | import ( 6 | "errors" 7 | 8 | "github.com/gopherjs/gopherjs/js" 9 | ) 10 | 11 | func runtime_args() []string { // not called on Windows 12 | return Args 13 | } 14 | 15 | func init() { 16 | if process := js.Global.Get("process"); process != js.Undefined { 17 | argv := process.Get("argv") 18 | Args = make([]string, argv.Length()-1) 19 | for i := 0; i < argv.Length()-1; i++ { 20 | Args[i] = argv.Index(i + 1).String() 21 | } 22 | } 23 | if len(Args) == 0 { 24 | Args = []string{"?"} 25 | } 26 | } 27 | 28 | func runtime_beforeExit() {} 29 | 30 | func executable() (string, error) { 31 | return "", errors.New("Executable not implemented for GOARCH=js") 32 | } 33 | -------------------------------------------------------------------------------- /compiler/natives/src/os/signal/signal.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package signal 4 | 5 | // Package signal is not implemented for GOARCH=js. 6 | 7 | func signal_disable(uint32) {} 8 | func signal_enable(uint32) {} 9 | func signal_ignore(uint32) {} 10 | func signal_recv() uint32 { return 0 } 11 | 12 | func loop() {} 13 | -------------------------------------------------------------------------------- /compiler/natives/src/reflect/example_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package reflect_test 4 | 5 | import "fmt" 6 | 7 | func ExampleStructOf() { 8 | // GopherJS does not implement reflect.addReflectOff needed for this test. 9 | // See https://github.com/gopherjs/gopherjs/issues/499 10 | 11 | fmt.Println(`value: &{Height:0.4 Age:2} 12 | json: {"height":0.4,"age":2} 13 | value: &{Height:1.5 Age:10}`) 14 | } 15 | -------------------------------------------------------------------------------- /compiler/natives/src/reflect/reflect_go111.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | // +build !go1.11.1 3 | 4 | package reflect 5 | 6 | import ( 7 | "unsafe" 8 | 9 | "github.com/gopherjs/gopherjs/js" 10 | ) 11 | 12 | func methodReceiver(op string, v Value, i int) (_, t *rtype, fn unsafe.Pointer) { 13 | var prop string 14 | if v.typ.Kind() == Interface { 15 | tt := (*interfaceType)(unsafe.Pointer(v.typ)) 16 | if i < 0 || i >= len(tt.methods) { 17 | panic("reflect: internal error: invalid method index") 18 | } 19 | m := &tt.methods[i] 20 | if !tt.nameOff(m.name).isExported() { 21 | panic("reflect: " + op + " of unexported method") 22 | } 23 | t = tt.typeOff(m.typ) 24 | prop = tt.nameOff(m.name).name() 25 | } else { 26 | ms := v.typ.exportedMethods() 27 | if uint(i) >= uint(len(ms)) { 28 | panic("reflect: internal error: invalid method index") 29 | } 30 | m := ms[i] 31 | if !v.typ.nameOff(m.name).isExported() { 32 | panic("reflect: " + op + " of unexported method") 33 | } 34 | t = v.typ.typeOff(m.mtyp) 35 | prop = js.Global.Call("$methodSet", jsType(v.typ)).Index(i).Get("prop").String() 36 | } 37 | rcvr := v.object() 38 | if isWrapped(v.typ) { 39 | rcvr = jsType(v.typ).New(rcvr) 40 | } 41 | fn = unsafe.Pointer(rcvr.Get(prop).Unsafe()) 42 | return 43 | } 44 | 45 | func (v Value) call(op string, in []Value) []Value { 46 | var ( 47 | t *rtype 48 | fn unsafe.Pointer 49 | rcvr *js.Object 50 | ) 51 | if v.flag&flagMethod != 0 { 52 | _, t, fn = methodReceiver(op, v, int(v.flag)>>flagMethodShift) 53 | rcvr = v.object() 54 | if isWrapped(v.typ) { 55 | rcvr = jsType(v.typ).New(rcvr) 56 | } 57 | } else { 58 | t = v.typ 59 | fn = unsafe.Pointer(v.object().Unsafe()) 60 | rcvr = js.Undefined 61 | } 62 | 63 | if fn == nil { 64 | panic("reflect.Value.Call: call of nil function") 65 | } 66 | 67 | isSlice := op == "CallSlice" 68 | n := t.NumIn() 69 | if isSlice { 70 | if !t.IsVariadic() { 71 | panic("reflect: CallSlice of non-variadic function") 72 | } 73 | if len(in) < n { 74 | panic("reflect: CallSlice with too few input arguments") 75 | } 76 | if len(in) > n { 77 | panic("reflect: CallSlice with too many input arguments") 78 | } 79 | } else { 80 | if t.IsVariadic() { 81 | n-- 82 | } 83 | if len(in) < n { 84 | panic("reflect: Call with too few input arguments") 85 | } 86 | if !t.IsVariadic() && len(in) > n { 87 | panic("reflect: Call with too many input arguments") 88 | } 89 | } 90 | for _, x := range in { 91 | if x.Kind() == Invalid { 92 | panic("reflect: " + op + " using zero Value argument") 93 | } 94 | } 95 | for i := 0; i < n; i++ { 96 | if xt, targ := in[i].Type(), t.In(i); !xt.AssignableTo(targ) { 97 | panic("reflect: " + op + " using " + xt.String() + " as type " + targ.String()) 98 | } 99 | } 100 | if !isSlice && t.IsVariadic() { 101 | // prepare slice for remaining values 102 | m := len(in) - n 103 | slice := MakeSlice(t.In(n), m, m) 104 | elem := t.In(n).Elem() 105 | for i := 0; i < m; i++ { 106 | x := in[n+i] 107 | if xt := x.Type(); !xt.AssignableTo(elem) { 108 | panic("reflect: cannot use " + xt.String() + " as type " + elem.String() + " in " + op) 109 | } 110 | slice.Index(i).Set(x) 111 | } 112 | origIn := in 113 | in = make([]Value, n+1) 114 | copy(in[:n], origIn) 115 | in[n] = slice 116 | } 117 | 118 | nin := len(in) 119 | if nin != t.NumIn() { 120 | panic("reflect.Value.Call: wrong argument count") 121 | } 122 | nout := t.NumOut() 123 | 124 | argsArray := js.Global.Get("Array").New(t.NumIn()) 125 | for i, arg := range in { 126 | argsArray.SetIndex(i, unwrapJsObject(t.In(i), arg.assignTo("reflect.Value.Call", t.In(i).common(), nil).object())) 127 | } 128 | results := callHelper(js.InternalObject(fn), rcvr, argsArray) 129 | 130 | switch nout { 131 | case 0: 132 | return nil 133 | case 1: 134 | return []Value{makeValue(t.Out(0), wrapJsObject(t.Out(0), results), 0)} 135 | default: 136 | ret := make([]Value, nout) 137 | for i := range ret { 138 | ret[i] = makeValue(t.Out(i), wrapJsObject(t.Out(i), results.Index(i)), 0) 139 | } 140 | return ret 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /compiler/natives/src/reflect/reflect_go1111.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | // +build go1.11.1 3 | 4 | package reflect 5 | 6 | import ( 7 | "unsafe" 8 | 9 | "github.com/gopherjs/gopherjs/js" 10 | ) 11 | 12 | func methodReceiver(op string, v Value, i int) (_ *rtype, t *funcType, fn unsafe.Pointer) { 13 | var prop string 14 | if v.typ.Kind() == Interface { 15 | tt := (*interfaceType)(unsafe.Pointer(v.typ)) 16 | if i < 0 || i >= len(tt.methods) { 17 | panic("reflect: internal error: invalid method index") 18 | } 19 | m := &tt.methods[i] 20 | if !tt.nameOff(m.name).isExported() { 21 | panic("reflect: " + op + " of unexported method") 22 | } 23 | t = (*funcType)(unsafe.Pointer(tt.typeOff(m.typ))) 24 | prop = tt.nameOff(m.name).name() 25 | } else { 26 | ms := v.typ.exportedMethods() 27 | if uint(i) >= uint(len(ms)) { 28 | panic("reflect: internal error: invalid method index") 29 | } 30 | m := ms[i] 31 | if !v.typ.nameOff(m.name).isExported() { 32 | panic("reflect: " + op + " of unexported method") 33 | } 34 | t = (*funcType)(unsafe.Pointer(v.typ.typeOff(m.mtyp))) 35 | prop = js.Global.Call("$methodSet", jsType(v.typ)).Index(i).Get("prop").String() 36 | } 37 | rcvr := v.object() 38 | if isWrapped(v.typ) { 39 | rcvr = jsType(v.typ).New(rcvr) 40 | } 41 | fn = unsafe.Pointer(rcvr.Get(prop).Unsafe()) 42 | return 43 | } 44 | 45 | func (v Value) call(op string, in []Value) []Value { 46 | var ( 47 | t *funcType 48 | fn unsafe.Pointer 49 | rcvr *js.Object 50 | ) 51 | if v.flag&flagMethod != 0 { 52 | _, t, fn = methodReceiver(op, v, int(v.flag)>>flagMethodShift) 53 | rcvr = v.object() 54 | if isWrapped(v.typ) { 55 | rcvr = jsType(v.typ).New(rcvr) 56 | } 57 | } else { 58 | t = (*funcType)(unsafe.Pointer(v.typ)) 59 | fn = unsafe.Pointer(v.object().Unsafe()) 60 | rcvr = js.Undefined 61 | } 62 | 63 | if fn == nil { 64 | panic("reflect.Value.Call: call of nil function") 65 | } 66 | 67 | isSlice := op == "CallSlice" 68 | n := t.NumIn() 69 | if isSlice { 70 | if !t.IsVariadic() { 71 | panic("reflect: CallSlice of non-variadic function") 72 | } 73 | if len(in) < n { 74 | panic("reflect: CallSlice with too few input arguments") 75 | } 76 | if len(in) > n { 77 | panic("reflect: CallSlice with too many input arguments") 78 | } 79 | } else { 80 | if t.IsVariadic() { 81 | n-- 82 | } 83 | if len(in) < n { 84 | panic("reflect: Call with too few input arguments") 85 | } 86 | if !t.IsVariadic() && len(in) > n { 87 | panic("reflect: Call with too many input arguments") 88 | } 89 | } 90 | for _, x := range in { 91 | if x.Kind() == Invalid { 92 | panic("reflect: " + op + " using zero Value argument") 93 | } 94 | } 95 | for i := 0; i < n; i++ { 96 | if xt, targ := in[i].Type(), t.In(i); !xt.AssignableTo(targ) { 97 | panic("reflect: " + op + " using " + xt.String() + " as type " + targ.String()) 98 | } 99 | } 100 | if !isSlice && t.IsVariadic() { 101 | // prepare slice for remaining values 102 | m := len(in) - n 103 | slice := MakeSlice(t.In(n), m, m) 104 | elem := t.In(n).Elem() 105 | for i := 0; i < m; i++ { 106 | x := in[n+i] 107 | if xt := x.Type(); !xt.AssignableTo(elem) { 108 | panic("reflect: cannot use " + xt.String() + " as type " + elem.String() + " in " + op) 109 | } 110 | slice.Index(i).Set(x) 111 | } 112 | origIn := in 113 | in = make([]Value, n+1) 114 | copy(in[:n], origIn) 115 | in[n] = slice 116 | } 117 | 118 | nin := len(in) 119 | if nin != t.NumIn() { 120 | panic("reflect.Value.Call: wrong argument count") 121 | } 122 | nout := t.NumOut() 123 | 124 | argsArray := js.Global.Get("Array").New(t.NumIn()) 125 | for i, arg := range in { 126 | argsArray.SetIndex(i, unwrapJsObject(t.In(i), arg.assignTo("reflect.Value.Call", t.In(i).common(), nil).object())) 127 | } 128 | results := callHelper(js.InternalObject(fn), rcvr, argsArray) 129 | 130 | switch nout { 131 | case 0: 132 | return nil 133 | case 1: 134 | return []Value{makeValue(t.Out(0), wrapJsObject(t.Out(0), results), 0)} 135 | default: 136 | ret := make([]Value, nout) 137 | for i := range ret { 138 | ret[i] = makeValue(t.Out(i), wrapJsObject(t.Out(i), results.Index(i)), 0) 139 | } 140 | return ret 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /compiler/natives/src/reflect/reflect_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package reflect_test 4 | 5 | import ( 6 | "math" 7 | "reflect" 8 | "testing" 9 | ) 10 | 11 | func TestAlignment(t *testing.T) { 12 | t.Skip() 13 | } 14 | 15 | func TestSliceOverflow(t *testing.T) { 16 | t.Skip() 17 | } 18 | 19 | func TestFuncLayout(t *testing.T) { 20 | t.Skip() 21 | } 22 | 23 | func TestArrayOfDirectIface(t *testing.T) { 24 | t.Skip() 25 | } 26 | 27 | func TestTypelinksSorted(t *testing.T) { 28 | t.Skip() 29 | } 30 | 31 | func TestGCBits(t *testing.T) { 32 | t.Skip() 33 | } 34 | 35 | func TestChanAlloc(t *testing.T) { 36 | t.Skip() 37 | } 38 | 39 | func TestNameBytesAreAligned(t *testing.T) { 40 | t.Skip() 41 | } 42 | 43 | func TestOffsetLock(t *testing.T) { 44 | t.Skip() 45 | } 46 | 47 | func TestSelectOnInvalid(t *testing.T) { 48 | reflect.Select([]reflect.SelectCase{ 49 | { 50 | Dir: reflect.SelectRecv, 51 | Chan: reflect.Value{}, 52 | }, { 53 | Dir: reflect.SelectSend, 54 | Chan: reflect.Value{}, 55 | Send: reflect.ValueOf(1), 56 | }, { 57 | Dir: reflect.SelectDefault, 58 | }, 59 | }) 60 | } 61 | 62 | func TestStructOfFieldName(t *testing.T) { 63 | t.Skip("StructOf") 64 | } 65 | 66 | func TestStructOf(t *testing.T) { 67 | t.Skip("StructOf") 68 | } 69 | 70 | func TestStructOfExportRules(t *testing.T) { 71 | t.Skip("StructOf") 72 | } 73 | 74 | func TestStructOfGC(t *testing.T) { 75 | t.Skip("StructOf") 76 | } 77 | 78 | func TestStructOfAlg(t *testing.T) { 79 | t.Skip("StructOf") 80 | } 81 | 82 | func TestStructOfGenericAlg(t *testing.T) { 83 | t.Skip("StructOf") 84 | } 85 | 86 | func TestStructOfDirectIface(t *testing.T) { 87 | t.Skip("StructOf") 88 | } 89 | 90 | func TestStructOfWithInterface(t *testing.T) { 91 | t.Skip("StructOf") 92 | } 93 | 94 | func TestStructOfTooManyFields(t *testing.T) { 95 | t.Skip("StructOf") 96 | } 97 | 98 | var deepEqualTests = []DeepEqualTest{ 99 | // Equalities 100 | {nil, nil, true}, 101 | {1, 1, true}, 102 | {int32(1), int32(1), true}, 103 | {0.5, 0.5, true}, 104 | {float32(0.5), float32(0.5), true}, 105 | {"hello", "hello", true}, 106 | {make([]int, 10), make([]int, 10), true}, 107 | {&[3]int{1, 2, 3}, &[3]int{1, 2, 3}, true}, 108 | {Basic{1, 0.5}, Basic{1, 0.5}, true}, 109 | {error(nil), error(nil), true}, 110 | {map[int]string{1: "one", 2: "two"}, map[int]string{2: "two", 1: "one"}, true}, 111 | {fn1, fn2, true}, 112 | 113 | // Inequalities 114 | {1, 2, false}, 115 | {int32(1), int32(2), false}, 116 | {0.5, 0.6, false}, 117 | {float32(0.5), float32(0.6), false}, 118 | {"hello", "hey", false}, 119 | {make([]int, 10), make([]int, 11), false}, 120 | {&[3]int{1, 2, 3}, &[3]int{1, 2, 4}, false}, 121 | {Basic{1, 0.5}, Basic{1, 0.6}, false}, 122 | {Basic{1, 0}, Basic{2, 0}, false}, 123 | {map[int]string{1: "one", 3: "two"}, map[int]string{2: "two", 1: "one"}, false}, 124 | {map[int]string{1: "one", 2: "txo"}, map[int]string{2: "two", 1: "one"}, false}, 125 | {map[int]string{1: "one"}, map[int]string{2: "two", 1: "one"}, false}, 126 | {map[int]string{2: "two", 1: "one"}, map[int]string{1: "one"}, false}, 127 | {nil, 1, false}, 128 | {1, nil, false}, 129 | {fn1, fn3, false}, 130 | {fn3, fn3, false}, 131 | {[][]int{{1}}, [][]int{{2}}, false}, 132 | {math.NaN(), math.NaN(), false}, 133 | {&[1]float64{math.NaN()}, &[1]float64{math.NaN()}, false}, 134 | {&[1]float64{math.NaN()}, self{}, true}, 135 | {[]float64{math.NaN()}, []float64{math.NaN()}, false}, 136 | {[]float64{math.NaN()}, self{}, true}, 137 | {map[float64]float64{math.NaN(): 1}, map[float64]float64{1: 2}, false}, 138 | {map[float64]float64{math.NaN(): 1}, self{}, true}, 139 | 140 | // Nil vs empty: not the same. 141 | {[]int{}, []int(nil), false}, 142 | {[]int{}, []int{}, true}, 143 | {[]int(nil), []int(nil), true}, 144 | {map[int]int{}, map[int]int(nil), false}, 145 | {map[int]int{}, map[int]int{}, true}, 146 | {map[int]int(nil), map[int]int(nil), true}, 147 | 148 | // Mismatched types 149 | {1, 1.0, false}, 150 | {int32(1), int64(1), false}, 151 | {0.5, "hello", false}, 152 | {[]int{1, 2, 3}, [3]int{1, 2, 3}, false}, 153 | {&[3]interface{}{1, 2, 4}, &[3]interface{}{1, 2, "s"}, false}, 154 | {Basic{1, 0.5}, NotBasic{1, 0.5}, false}, 155 | {map[uint]string{1: "one", 2: "two"}, map[int]string{2: "two", 1: "one"}, false}, 156 | 157 | // Possible loops. 158 | {&loop1, &loop1, true}, 159 | //{&loop1, &loop2, true}, // TODO: Fix. 160 | {&loopy1, &loopy1, true}, 161 | //{&loopy1, &loopy2, true}, // TODO: Fix. 162 | } 163 | 164 | // TODO: Fix this. See https://github.com/gopherjs/gopherjs/issues/763. 165 | func TestIssue22073(t *testing.T) { 166 | m := reflect.ValueOf(NonExportedFirst(0)).Method(0) 167 | 168 | if got := m.Type().NumOut(); got != 0 { 169 | t.Errorf("NumOut: got %v, want 0", got) 170 | } 171 | 172 | // TODO: Fix this. The call below fails with: 173 | // 174 | // var $call = function(fn, rcvr, args) { return fn.apply(rcvr, args); }; 175 | // ^ 176 | // TypeError: Cannot read property 'apply' of undefined 177 | 178 | // Shouldn't panic. 179 | //m.Call(nil) 180 | } 181 | 182 | func TestCallReturnsEmpty(t *testing.T) { 183 | t.Skip("test uses runtime.SetFinalizer, which is not supported by GopherJS") 184 | } 185 | 186 | func init() { 187 | // TODO: This is a failure in 1.11, try to determine the cause and fix. 188 | typeTests = append(typeTests[:31], typeTests[32:]...) // skip test case #31 189 | } 190 | -------------------------------------------------------------------------------- /compiler/natives/src/reflect/swapper.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package reflect 4 | 5 | import "github.com/gopherjs/gopherjs/js" 6 | 7 | func Swapper(slice interface{}) func(i, j int) { 8 | v := ValueOf(slice) 9 | if v.Kind() != Slice { 10 | panic(&ValueError{Method: "Swapper", Kind: v.Kind()}) 11 | } 12 | // Fast path for slices of size 0 and 1. Nothing to swap. 13 | vLen := uint(v.Len()) 14 | switch vLen { 15 | case 0: 16 | return func(i, j int) { panic("reflect: slice index out of range") } 17 | case 1: 18 | return func(i, j int) { 19 | if i != 0 || j != 0 { 20 | panic("reflect: slice index out of range") 21 | } 22 | } 23 | } 24 | a := js.InternalObject(slice).Get("$array") 25 | off := js.InternalObject(slice).Get("$offset").Int() 26 | return func(i, j int) { 27 | if uint(i) >= vLen || uint(j) >= vLen { 28 | panic("reflect: slice index out of range") 29 | } 30 | i += off 31 | j += off 32 | tmp := a.Index(i) 33 | a.SetIndex(i, a.Index(j)) 34 | a.SetIndex(j, tmp) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /compiler/natives/src/regexp/regexp_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package regexp 4 | 5 | import ( 6 | "testing" 7 | ) 8 | 9 | func TestOnePassCutoff(t *testing.T) { 10 | t.Skip() // "Maximum call stack size exceeded" on V8 11 | } 12 | -------------------------------------------------------------------------------- /compiler/natives/src/runtime/debug/debug.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package debug 4 | 5 | func setGCPercent(int32) int32 { 6 | // Not implemented. Return initial setting. 7 | return 100 8 | } 9 | 10 | func setMaxStack(bytes int) int { 11 | // Not implemented. Return initial setting. 12 | // The initial setting is 1 GB on 64-bit systems, 250 MB on 32-bit systems. 13 | return 250000000 14 | } 15 | -------------------------------------------------------------------------------- /compiler/natives/src/runtime/internal/sys/sys.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package sys 4 | 5 | type Uintreg uint32 6 | 7 | const GoarchArm64 = 0 8 | -------------------------------------------------------------------------------- /compiler/natives/src/runtime/pprof/pprof.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package pprof 4 | 5 | import ( 6 | "io" 7 | "sync" 8 | ) 9 | 10 | type Profile struct { 11 | name string 12 | mu sync.Mutex 13 | m map[interface{}][]uintptr 14 | count func() int 15 | write func(io.Writer, int) error 16 | } 17 | 18 | func (p *Profile) WriteTo(w io.Writer, debug int) error { 19 | return nil 20 | } 21 | 22 | func (p *Profile) Count() int { 23 | return 0 24 | } 25 | 26 | func (p *Profile) Name() string { 27 | return "" 28 | } 29 | 30 | func (p *Profile) Add(value interface{}, skip int) { 31 | } 32 | 33 | func (p *Profile) Remove(value interface{}) { 34 | } 35 | 36 | func StartCPUProfile(w io.Writer) error { 37 | return nil 38 | } 39 | 40 | func StopCPUProfile() { 41 | } 42 | 43 | func WriteHeapProfile(w io.Writer) error { 44 | return nil 45 | } 46 | 47 | func Lookup(name string) *Profile { 48 | return nil 49 | } 50 | -------------------------------------------------------------------------------- /compiler/natives/src/runtime/runtime.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package runtime 4 | 5 | import ( 6 | "runtime/internal/sys" 7 | 8 | "github.com/gopherjs/gopherjs/js" 9 | ) 10 | 11 | const GOOS = sys.GOOS 12 | const GOARCH = "js" 13 | const Compiler = "gopherjs" 14 | 15 | // fake for error.go 16 | type eface struct { 17 | _type *_type 18 | } 19 | type _type struct { 20 | str string 21 | } 22 | 23 | func (t *_type) string() string { 24 | return t.str 25 | } 26 | 27 | func (t *_type) pkgpath() string { 28 | return "" 29 | } 30 | 31 | func init() { 32 | jsPkg := js.Global.Get("$packages").Get("github.com/gopherjs/gopherjs/js") 33 | js.Global.Set("$jsObjectPtr", jsPkg.Get("Object").Get("ptr")) 34 | js.Global.Set("$jsErrorPtr", jsPkg.Get("Error").Get("ptr")) 35 | js.Global.Set("$throwRuntimeError", js.InternalObject(throw)) 36 | // avoid dead code elimination 37 | var e error 38 | e = &TypeAssertionError{} 39 | _ = e 40 | } 41 | 42 | func GOROOT() string { 43 | process := js.Global.Get("process") 44 | if process == js.Undefined { 45 | return "/" 46 | } 47 | goroot := process.Get("env").Get("GOROOT") 48 | if goroot != js.Undefined { 49 | return goroot.String() 50 | } 51 | // sys.DefaultGoroot is now gone, can't use it as fallback anymore. 52 | // TODO: See if a better solution is needed. 53 | return "/usr/local/go" 54 | } 55 | 56 | func Breakpoint() { 57 | js.Debugger() 58 | } 59 | 60 | func Caller(skip int) (pc uintptr, file string, line int, ok bool) { 61 | info := js.Global.Get("Error").New().Get("stack").Call("split", "\n").Index(skip + 2) 62 | if info == js.Undefined { 63 | return 0, "", 0, false 64 | } 65 | parts := info.Call("substring", info.Call("indexOf", "(").Int()+1, info.Call("indexOf", ")").Int()).Call("split", ":") 66 | return 0, parts.Index(0).String(), parts.Index(1).Int(), true 67 | } 68 | 69 | func Callers(skip int, pc []uintptr) int { 70 | return 0 71 | } 72 | 73 | // CallersFrames is not implemented for GOARCH=js. 74 | // TODO: Implement if possible. 75 | func CallersFrames(callers []uintptr) *Frames { return &Frames{} } 76 | 77 | type Frames struct{} 78 | 79 | func (ci *Frames) Next() (frame Frame, more bool) { return } 80 | 81 | type Frame struct { 82 | PC uintptr 83 | Func *Func 84 | Function string 85 | File string 86 | Line int 87 | Entry uintptr 88 | } 89 | 90 | func GC() { 91 | } 92 | 93 | func Goexit() { 94 | js.Global.Get("$curGoroutine").Set("exit", true) 95 | js.Global.Call("$throw", nil) 96 | } 97 | 98 | func GOMAXPROCS(n int) int { 99 | return 1 100 | } 101 | 102 | func Gosched() { 103 | c := make(chan struct{}) 104 | js.Global.Call("$setTimeout", js.InternalObject(func() { close(c) }), 0) 105 | <-c 106 | } 107 | 108 | func NumCPU() int { 109 | return 1 110 | } 111 | 112 | func NumGoroutine() int { 113 | return js.Global.Get("$totalGoroutines").Int() 114 | } 115 | 116 | type MemStats struct { 117 | // General statistics. 118 | Alloc uint64 // bytes allocated and still in use 119 | TotalAlloc uint64 // bytes allocated (even if freed) 120 | Sys uint64 // bytes obtained from system (sum of XxxSys below) 121 | Lookups uint64 // number of pointer lookups 122 | Mallocs uint64 // number of mallocs 123 | Frees uint64 // number of frees 124 | 125 | // Main allocation heap statistics. 126 | HeapAlloc uint64 // bytes allocated and still in use 127 | HeapSys uint64 // bytes obtained from system 128 | HeapIdle uint64 // bytes in idle spans 129 | HeapInuse uint64 // bytes in non-idle span 130 | HeapReleased uint64 // bytes released to the OS 131 | HeapObjects uint64 // total number of allocated objects 132 | 133 | // Low-level fixed-size structure allocator statistics. 134 | // Inuse is bytes used now. 135 | // Sys is bytes obtained from system. 136 | StackInuse uint64 // bytes used by stack allocator 137 | StackSys uint64 138 | MSpanInuse uint64 // mspan structures 139 | MSpanSys uint64 140 | MCacheInuse uint64 // mcache structures 141 | MCacheSys uint64 142 | BuckHashSys uint64 // profiling bucket hash table 143 | GCSys uint64 // GC metadata 144 | OtherSys uint64 // other system allocations 145 | 146 | // Garbage collector statistics. 147 | NextGC uint64 // next collection will happen when HeapAlloc ≥ this amount 148 | LastGC uint64 // end time of last collection (nanoseconds since 1970) 149 | PauseTotalNs uint64 150 | PauseNs [256]uint64 // circular buffer of recent GC pause durations, most recent at [(NumGC+255)%256] 151 | PauseEnd [256]uint64 // circular buffer of recent GC pause end times 152 | NumGC uint32 153 | GCCPUFraction float64 // fraction of CPU time used by GC 154 | EnableGC bool 155 | DebugGC bool 156 | 157 | // Per-size allocation statistics. 158 | // 61 is NumSizeClasses in the C code. 159 | BySize [61]struct { 160 | Size uint32 161 | Mallocs uint64 162 | Frees uint64 163 | } 164 | } 165 | 166 | func ReadMemStats(m *MemStats) { 167 | } 168 | 169 | func SetFinalizer(x, f interface{}) { 170 | } 171 | 172 | type Func struct { 173 | opaque struct{} // unexported field to disallow conversions 174 | } 175 | 176 | func (_ *Func) Entry() uintptr { return 0 } 177 | func (_ *Func) FileLine(pc uintptr) (file string, line int) { return "", 0 } 178 | func (_ *Func) Name() string { return "" } 179 | 180 | func FuncForPC(pc uintptr) *Func { 181 | return nil 182 | } 183 | 184 | var MemProfileRate int = 512 * 1024 185 | 186 | func SetBlockProfileRate(rate int) { 187 | } 188 | 189 | func SetMutexProfileFraction(rate int) int { 190 | // TODO: Investigate this. If it's possible to implement, consider doing so, otherwise remove this comment. 191 | return 0 192 | } 193 | 194 | func Stack(buf []byte, all bool) int { 195 | s := js.Global.Get("Error").New().Get("stack") 196 | if s == js.Undefined { 197 | return 0 198 | } 199 | return copy(buf, s.Call("substr", s.Call("indexOf", "\n").Int()+1).String()) 200 | } 201 | 202 | func LockOSThread() {} 203 | 204 | func UnlockOSThread() {} 205 | 206 | func Version() string { 207 | return sys.TheVersion 208 | } 209 | 210 | func StartTrace() error { return nil } 211 | func StopTrace() {} 212 | func ReadTrace() []byte 213 | 214 | // We fake a cgo environment to catch errors. Therefor we have to implement this and always return 0 215 | func NumCgoCall() int64 { 216 | return 0 217 | } 218 | 219 | func efaceOf(ep *interface{}) *eface { 220 | panic("efaceOf: not supported") 221 | } 222 | 223 | func KeepAlive(interface{}) {} 224 | 225 | func throw(s string) { 226 | panic(errorString(s)) 227 | } 228 | 229 | // These are used by panicwrap. Not implemented for GOARCH=js. 230 | // TODO: Implement if possible. 231 | func getcallerpc() uintptr { return 0 } 232 | func findfunc(pc uintptr) funcInfo { return funcInfo{} } 233 | func funcname(f funcInfo) string { return "" } 234 | 235 | type funcInfo struct{} 236 | -------------------------------------------------------------------------------- /compiler/natives/src/strings/strings.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package strings 4 | 5 | import ( 6 | "unicode/utf8" 7 | 8 | "github.com/gopherjs/gopherjs/js" 9 | ) 10 | 11 | func IndexByte(s string, c byte) int { 12 | return js.InternalObject(s).Call("indexOf", js.Global.Get("String").Call("fromCharCode", c)).Int() 13 | } 14 | 15 | func Index(s, sep string) int { 16 | return js.InternalObject(s).Call("indexOf", js.InternalObject(sep)).Int() 17 | } 18 | 19 | func LastIndex(s, sep string) int { 20 | return js.InternalObject(s).Call("lastIndexOf", js.InternalObject(sep)).Int() 21 | } 22 | 23 | func Count(s, sep string) int { 24 | n := 0 25 | // special cases 26 | switch { 27 | case len(sep) == 0: 28 | return utf8.RuneCountInString(s) + 1 29 | case len(sep) > len(s): 30 | return 0 31 | case len(sep) == len(s): 32 | if sep == s { 33 | return 1 34 | } 35 | return 0 36 | } 37 | 38 | for { 39 | pos := Index(s, sep) 40 | if pos == -1 { 41 | break 42 | } 43 | n++ 44 | s = s[pos+len(sep):] 45 | } 46 | return n 47 | } 48 | 49 | func (b *Builder) String() string { 50 | // Upstream Builder.String relies on package unsafe. We can't do that. 51 | // TODO: It's possible that the entire strings.Builder API can be implemented 52 | // more efficiently for GOARCH=js specifically (avoid using []byte, instead 53 | // use a String directly; or some JavaScript string builder API if one exists). 54 | // But this is more work, defer doing it until there's a need shown via profiling, 55 | // and there are benchmarks available (see https://github.com/golang/go/issues/18990#issuecomment-352068533). 56 | return string(b.buf) 57 | } 58 | 59 | func (b *Builder) copyCheck() { 60 | if b.addr == nil { 61 | // Upstream copyCheck uses noescape, which performs unsafe.Pointer manipulation. 62 | // We can't do that, so skip it. See https://github.com/golang/go/commit/484586c81a0196e42ac52f651bc56017ca454280. 63 | b.addr = b 64 | } else if b.addr != b { 65 | panic("strings: illegal use of non-zero Builder copied by value") 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /compiler/natives/src/strings/strings_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package strings_test 4 | 5 | import "testing" 6 | 7 | func TestBuilderAllocs(t *testing.T) { 8 | t.Skip("runtime.ReadMemStats, testing.AllocsPerRun not supported in GopherJS") 9 | } 10 | 11 | func TestBuilderGrow(t *testing.T) { 12 | t.Skip("runtime.ReadMemStats, testing.AllocsPerRun not supported in GopherJS") 13 | } 14 | 15 | func TestCompareStrings(t *testing.T) { 16 | t.Skip("unsafeString not supported in GopherJS") 17 | } 18 | -------------------------------------------------------------------------------- /compiler/natives/src/sync/atomic/atomic.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package atomic 4 | 5 | import ( 6 | "unsafe" 7 | 8 | "github.com/gopherjs/gopherjs/js" 9 | ) 10 | 11 | func SwapInt32(addr *int32, new int32) int32 { 12 | old := *addr 13 | *addr = new 14 | return old 15 | } 16 | 17 | func SwapInt64(addr *int64, new int64) int64 { 18 | old := *addr 19 | *addr = new 20 | return old 21 | } 22 | 23 | func SwapUint32(addr *uint32, new uint32) uint32 { 24 | old := *addr 25 | *addr = new 26 | return old 27 | } 28 | 29 | func SwapUint64(addr *uint64, new uint64) uint64 { 30 | old := *addr 31 | *addr = new 32 | return old 33 | } 34 | 35 | func SwapUintptr(addr *uintptr, new uintptr) uintptr { 36 | old := *addr 37 | *addr = new 38 | return old 39 | } 40 | 41 | func SwapPointer(addr *unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer { 42 | old := *addr 43 | *addr = new 44 | return old 45 | } 46 | 47 | func CompareAndSwapInt32(addr *int32, old, new int32) bool { 48 | if *addr == old { 49 | *addr = new 50 | return true 51 | } 52 | return false 53 | } 54 | 55 | func CompareAndSwapInt64(addr *int64, old, new int64) bool { 56 | if *addr == old { 57 | *addr = new 58 | return true 59 | } 60 | return false 61 | } 62 | 63 | func CompareAndSwapUint32(addr *uint32, old, new uint32) bool { 64 | if *addr == old { 65 | *addr = new 66 | return true 67 | } 68 | return false 69 | } 70 | 71 | func CompareAndSwapUint64(addr *uint64, old, new uint64) bool { 72 | if *addr == old { 73 | *addr = new 74 | return true 75 | } 76 | return false 77 | } 78 | 79 | func CompareAndSwapUintptr(addr *uintptr, old, new uintptr) bool { 80 | if *addr == old { 81 | *addr = new 82 | return true 83 | } 84 | return false 85 | } 86 | 87 | func CompareAndSwapPointer(addr *unsafe.Pointer, old, new unsafe.Pointer) bool { 88 | if *addr == old { 89 | *addr = new 90 | return true 91 | } 92 | return false 93 | } 94 | 95 | func AddInt32(addr *int32, delta int32) int32 { 96 | new := *addr + delta 97 | *addr = new 98 | return new 99 | } 100 | 101 | func AddUint32(addr *uint32, delta uint32) uint32 { 102 | new := *addr + delta 103 | *addr = new 104 | return new 105 | } 106 | 107 | func AddInt64(addr *int64, delta int64) int64 { 108 | new := *addr + delta 109 | *addr = new 110 | return new 111 | } 112 | 113 | func AddUint64(addr *uint64, delta uint64) uint64 { 114 | new := *addr + delta 115 | *addr = new 116 | return new 117 | } 118 | 119 | func AddUintptr(addr *uintptr, delta uintptr) uintptr { 120 | new := *addr + delta 121 | *addr = new 122 | return new 123 | } 124 | 125 | func LoadInt32(addr *int32) int32 { 126 | return *addr 127 | } 128 | 129 | func LoadInt64(addr *int64) int64 { 130 | return *addr 131 | } 132 | 133 | func LoadUint32(addr *uint32) uint32 { 134 | return *addr 135 | } 136 | 137 | func LoadUint64(addr *uint64) uint64 { 138 | return *addr 139 | } 140 | 141 | func LoadUintptr(addr *uintptr) uintptr { 142 | return *addr 143 | } 144 | 145 | func LoadPointer(addr *unsafe.Pointer) unsafe.Pointer { 146 | return *addr 147 | } 148 | 149 | func StoreInt32(addr *int32, val int32) { 150 | *addr = val 151 | } 152 | 153 | func StoreInt64(addr *int64, val int64) { 154 | *addr = val 155 | } 156 | 157 | func StoreUint32(addr *uint32, val uint32) { 158 | *addr = val 159 | } 160 | 161 | func StoreUint64(addr *uint64, val uint64) { 162 | *addr = val 163 | } 164 | 165 | func StoreUintptr(addr *uintptr, val uintptr) { 166 | *addr = val 167 | } 168 | 169 | func StorePointer(addr *unsafe.Pointer, val unsafe.Pointer) { 170 | *addr = val 171 | } 172 | 173 | func (v *Value) Load() (x interface{}) { 174 | return v.v 175 | } 176 | 177 | func (v *Value) Store(x interface{}) { 178 | if x == nil { 179 | panic("sync/atomic: store of nil value into Value") 180 | } 181 | if v.v != nil && js.InternalObject(x).Get("constructor") != js.InternalObject(v.v).Get("constructor") { 182 | panic("sync/atomic: store of inconsistently typed value into Value") 183 | } 184 | v.v = x 185 | } 186 | -------------------------------------------------------------------------------- /compiler/natives/src/sync/atomic/atomic_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package atomic_test 4 | 5 | import "testing" 6 | 7 | func TestHammerStoreLoad(t *testing.T) { 8 | t.Skip("use of unsafe") 9 | } 10 | -------------------------------------------------------------------------------- /compiler/natives/src/sync/cond.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package sync 4 | 5 | type Cond struct { 6 | // fields used by vanilla implementation 7 | noCopy noCopy 8 | L Locker 9 | notify notifyList 10 | checker copyChecker 11 | 12 | // fields used by new implementation 13 | n int 14 | ch chan bool 15 | } 16 | 17 | func (c *Cond) Wait() { 18 | c.n++ 19 | if c.ch == nil { 20 | c.ch = make(chan bool) 21 | } 22 | c.L.Unlock() 23 | <-c.ch 24 | c.L.Lock() 25 | } 26 | 27 | func (c *Cond) Signal() { 28 | if c.n == 0 { 29 | return 30 | } 31 | c.n-- 32 | c.ch <- true 33 | } 34 | 35 | func (c *Cond) Broadcast() { 36 | n := c.n 37 | c.n = 0 38 | for i := 0; i < n; i++ { 39 | c.ch <- true 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /compiler/natives/src/sync/export_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package sync 4 | 5 | // Referenced by tests, need to have no-op implementations. 6 | var Runtime_procPin = func() int { return 0 } 7 | var Runtime_procUnpin = func() {} 8 | -------------------------------------------------------------------------------- /compiler/natives/src/sync/pool.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package sync 4 | 5 | import "unsafe" 6 | 7 | type Pool struct { 8 | local unsafe.Pointer 9 | localSize uintptr 10 | 11 | store []interface{} 12 | New func() interface{} 13 | } 14 | 15 | func (p *Pool) Get() interface{} { 16 | if len(p.store) == 0 { 17 | if p.New != nil { 18 | return p.New() 19 | } 20 | return nil 21 | } 22 | x := p.store[len(p.store)-1] 23 | p.store = p.store[:len(p.store)-1] 24 | return x 25 | } 26 | 27 | func (p *Pool) Put(x interface{}) { 28 | if x == nil { 29 | return 30 | } 31 | p.store = append(p.store, x) 32 | } 33 | 34 | func runtime_registerPoolCleanup(cleanup func()) { 35 | } 36 | -------------------------------------------------------------------------------- /compiler/natives/src/sync/sync.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package sync 4 | 5 | import "github.com/gopherjs/gopherjs/js" 6 | 7 | var semWaiters = make(map[*uint32][]chan bool) 8 | 9 | // semAwoken tracks the number of waiters awoken by runtime_Semrelease (`ch <- true`) 10 | // that have not yet acquired the semaphore (`<-ch` in runtime_SemacquireMutex). 11 | // 12 | // This prevents a new call to runtime_SemacquireMutex to wrongly acquire the semaphore 13 | // in between (because runtime_Semrelease has already incremented the semaphore while 14 | // all the pending calls to runtime_SemacquireMutex have not yet received from the channel 15 | // and thus decremented the semaphore). 16 | // 17 | // See https://github.com/gopherjs/gopherjs/issues/736. 18 | var semAwoken = make(map[*uint32]uint32) 19 | 20 | func runtime_Semacquire(s *uint32) { 21 | runtime_SemacquireMutex(s, false) 22 | } 23 | 24 | // SemacquireMutex is like Semacquire, but for profiling contended Mutexes. 25 | // Mutex profiling is not supported, so just use the same implementation as runtime_Semacquire. 26 | // TODO: Investigate this. If it's possible to implement, consider doing so, otherwise remove this comment. 27 | func runtime_SemacquireMutex(s *uint32, lifo bool) { 28 | if (*s - semAwoken[s]) == 0 { 29 | ch := make(chan bool) 30 | if lifo { 31 | semWaiters[s] = append([]chan bool{ch}, semWaiters[s]...) 32 | } else { 33 | semWaiters[s] = append(semWaiters[s], ch) 34 | } 35 | <-ch 36 | semAwoken[s] -= 1 37 | if semAwoken[s] == 0 { 38 | delete(semAwoken, s) 39 | } 40 | } 41 | *s-- 42 | } 43 | 44 | func runtime_Semrelease(s *uint32, handoff bool) { 45 | // TODO: Use handoff if needed/possible. 46 | *s++ 47 | 48 | w := semWaiters[s] 49 | if len(w) == 0 { 50 | return 51 | } 52 | 53 | ch := w[0] 54 | w = w[1:] 55 | semWaiters[s] = w 56 | if len(w) == 0 { 57 | delete(semWaiters, s) 58 | } 59 | 60 | semAwoken[s] += 1 61 | 62 | ch <- true 63 | } 64 | 65 | func runtime_notifyListCheck(size uintptr) {} 66 | 67 | func runtime_canSpin(i int) bool { 68 | return false 69 | } 70 | 71 | // Copy of time.runtimeNano. 72 | func runtime_nanotime() int64 { 73 | const millisecond = 1000000 74 | return js.Global.Get("Date").New().Call("getTime").Int64() * millisecond 75 | } 76 | 77 | // Implemented in runtime. 78 | func throw(s string) { 79 | js.Global.Call("$throwRuntimeError", s) 80 | } 81 | -------------------------------------------------------------------------------- /compiler/natives/src/sync/sync_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package sync_test 4 | 5 | import ( 6 | "testing" 7 | ) 8 | 9 | func TestPool(t *testing.T) { 10 | t.Skip() 11 | } 12 | 13 | func TestPoolGC(t *testing.T) { 14 | t.Skip() 15 | } 16 | 17 | func TestPoolRelease(t *testing.T) { 18 | t.Skip() 19 | } 20 | 21 | func TestCondCopy(t *testing.T) { 22 | t.Skip() 23 | } 24 | -------------------------------------------------------------------------------- /compiler/natives/src/sync/waitgroup.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package sync 4 | 5 | type WaitGroup struct { 6 | counter int 7 | ch chan struct{} 8 | 9 | state1 [3]uint32 10 | } 11 | 12 | func (wg *WaitGroup) Add(delta int) { 13 | wg.counter += delta 14 | if wg.counter < 0 { 15 | panic("sync: negative WaitGroup counter") 16 | } 17 | if wg.counter > 0 && wg.ch == nil { 18 | wg.ch = make(chan struct{}) 19 | } 20 | if wg.counter == 0 && wg.ch != nil { 21 | close(wg.ch) 22 | wg.ch = nil 23 | } 24 | } 25 | 26 | func (wg *WaitGroup) Wait() { 27 | if wg.counter > 0 { 28 | <-wg.ch 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /compiler/natives/src/syscall/syscall.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package syscall 4 | 5 | import ( 6 | "unsafe" 7 | 8 | "github.com/gopherjs/gopherjs/js" 9 | ) 10 | 11 | var warningPrinted = false 12 | var lineBuffer []byte 13 | 14 | func init() { 15 | js.Global.Set("$flushConsole", js.InternalObject(func() { 16 | if len(lineBuffer) != 0 { 17 | js.Global.Get("console").Call("log", string(lineBuffer)) 18 | lineBuffer = nil 19 | } 20 | })) 21 | } 22 | 23 | func printWarning() { 24 | if !warningPrinted { 25 | js.Global.Get("console").Call("error", "warning: system calls not available, see https://github.com/gopherjs/gopherjs/blob/master/doc/syscalls.md") 26 | } 27 | warningPrinted = true 28 | } 29 | 30 | func printToConsole(b []byte) { 31 | goPrintToConsole := js.Global.Get("goPrintToConsole") 32 | if goPrintToConsole != js.Undefined { 33 | goPrintToConsole.Invoke(js.InternalObject(b)) 34 | return 35 | } 36 | 37 | lineBuffer = append(lineBuffer, b...) 38 | for { 39 | i := indexByte(lineBuffer, '\n') 40 | if i == -1 { 41 | break 42 | } 43 | js.Global.Get("console").Call("log", string(lineBuffer[:i])) // don't use println, since it does not externalize multibyte characters 44 | lineBuffer = lineBuffer[i+1:] 45 | } 46 | } 47 | 48 | func use(p unsafe.Pointer) { 49 | // no-op 50 | } 51 | 52 | func Exit(code int) { 53 | Syscall(exitTrap, uintptr(code), 0, 0) 54 | } 55 | 56 | // indexByte is copied from bytes package to avoid importing it (since the real syscall package doesn't). 57 | func indexByte(s []byte, c byte) int { 58 | for i, b := range s { 59 | if b == c { 60 | return i 61 | } 62 | } 63 | return -1 64 | } 65 | -------------------------------------------------------------------------------- /compiler/natives/src/syscall/syscall_darwin.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package syscall 4 | 5 | import ( 6 | "github.com/gopherjs/gopherjs/js" 7 | ) 8 | 9 | func funcPC(f func()) uintptr { 10 | if js.InternalObject(f) == js.InternalObject(libc_write_trampoline) { 11 | return SYS_WRITE 12 | } 13 | return uintptr(minusOne) 14 | } 15 | 16 | func syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) { 17 | return Syscall(trap, a1, a2, a3) 18 | } 19 | 20 | func syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) { 21 | return Syscall6(trap, a1, a2, a3, a4, a5, a6) 22 | } 23 | 24 | func syscall6X(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) { 25 | panic("syscall6X is not implemented") 26 | } 27 | 28 | func rawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) { 29 | return RawSyscall(trap, a1, a2, a3) 30 | } 31 | 32 | func rawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) { 33 | return RawSyscall6(trap, a1, a2, a3, a4, a5, a6) 34 | } 35 | -------------------------------------------------------------------------------- /compiler/natives/src/syscall/syscall_linux.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package syscall 4 | 5 | const exitTrap = SYS_EXIT_GROUP 6 | -------------------------------------------------------------------------------- /compiler/natives/src/syscall/syscall_nonlinux.go: -------------------------------------------------------------------------------- 1 | // +build js,!linux 2 | 3 | package syscall 4 | 5 | const exitTrap = SYS_EXIT 6 | -------------------------------------------------------------------------------- /compiler/natives/src/syscall/syscall_unix.go: -------------------------------------------------------------------------------- 1 | // +build js,!windows 2 | 3 | package syscall 4 | 5 | import ( 6 | "runtime" 7 | "unsafe" 8 | 9 | "github.com/gopherjs/gopherjs/js" 10 | ) 11 | 12 | func runtime_envs() []string { 13 | process := js.Global.Get("process") 14 | if process == js.Undefined { 15 | return nil 16 | } 17 | jsEnv := process.Get("env") 18 | envkeys := js.Global.Get("Object").Call("keys", jsEnv) 19 | envs := make([]string, envkeys.Length()) 20 | for i := 0; i < envkeys.Length(); i++ { 21 | key := envkeys.Index(i).String() 22 | envs[i] = key + "=" + jsEnv.Get(key).String() 23 | } 24 | return envs 25 | } 26 | 27 | func setenv_c(k, v string) { 28 | process := js.Global.Get("process") 29 | if process == js.Undefined { 30 | return 31 | } 32 | process.Get("env").Set(k, v) 33 | } 34 | 35 | func unsetenv_c(k string) { 36 | process := js.Global.Get("process") 37 | if process == js.Undefined { 38 | return 39 | } 40 | process.Get("env").Delete(k) 41 | } 42 | 43 | var syscallModule *js.Object 44 | var alreadyTriedToLoad = false 45 | var minusOne = -1 46 | 47 | func syscallByName(name string) *js.Object { 48 | defer func() { 49 | recover() 50 | // return nil if recovered 51 | }() 52 | if syscallModule == nil { 53 | if alreadyTriedToLoad { 54 | return nil 55 | } 56 | alreadyTriedToLoad = true 57 | require := js.Global.Get("require") 58 | if require == js.Undefined { 59 | panic("") 60 | } 61 | syscallModule = require.Invoke("syscall") 62 | } 63 | return syscallModule.Get(name) 64 | } 65 | 66 | func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) { 67 | if f := syscallByName("Syscall"); f != nil { 68 | r := f.Invoke(trap, a1, a2, a3) 69 | return uintptr(r.Index(0).Int()), uintptr(r.Index(1).Int()), Errno(r.Index(2).Int()) 70 | } 71 | if trap == SYS_WRITE && (a1 == 1 || a1 == 2) { 72 | array := js.InternalObject(a2) 73 | slice := make([]byte, array.Length()) 74 | js.InternalObject(slice).Set("$array", array) 75 | printToConsole(slice) 76 | return uintptr(array.Length()), 0, 0 77 | } 78 | if trap == exitTrap { 79 | runtime.Goexit() 80 | } 81 | printWarning() 82 | return uintptr(minusOne), 0, EACCES 83 | } 84 | 85 | func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) { 86 | if f := syscallByName("Syscall6"); f != nil { 87 | r := f.Invoke(trap, a1, a2, a3, a4, a5, a6) 88 | return uintptr(r.Index(0).Int()), uintptr(r.Index(1).Int()), Errno(r.Index(2).Int()) 89 | } 90 | if trap != 202 { // kern.osrelease on OS X, happens in init of "os" package 91 | printWarning() 92 | } 93 | return uintptr(minusOne), 0, EACCES 94 | } 95 | 96 | func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) { 97 | if f := syscallByName("Syscall"); f != nil { 98 | r := f.Invoke(trap, a1, a2, a3) 99 | return uintptr(r.Index(0).Int()), uintptr(r.Index(1).Int()), Errno(r.Index(2).Int()) 100 | } 101 | printWarning() 102 | return uintptr(minusOne), 0, EACCES 103 | } 104 | 105 | func rawSyscallNoError(trap, a1, a2, a3 uintptr) (r1, r2 uintptr) { 106 | if f := syscallByName("Syscall"); f != nil { 107 | r := f.Invoke(trap, a1, a2, a3) 108 | return uintptr(r.Index(0).Int()), uintptr(r.Index(1).Int()) 109 | } 110 | printWarning() 111 | return uintptr(minusOne), 0 112 | } 113 | 114 | func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) { 115 | if f := syscallByName("Syscall6"); f != nil { 116 | r := f.Invoke(trap, a1, a2, a3, a4, a5, a6) 117 | return uintptr(r.Index(0).Int()), uintptr(r.Index(1).Int()), Errno(r.Index(2).Int()) 118 | } 119 | printWarning() 120 | return uintptr(minusOne), 0, EACCES 121 | } 122 | 123 | func BytePtrFromString(s string) (*byte, error) { 124 | array := js.Global.Get("Uint8Array").New(len(s) + 1) 125 | for i, b := range []byte(s) { 126 | if b == 0 { 127 | return nil, EINVAL 128 | } 129 | array.SetIndex(i, b) 130 | } 131 | array.SetIndex(len(s), 0) 132 | return (*byte)(unsafe.Pointer(array.Unsafe())), nil 133 | } 134 | -------------------------------------------------------------------------------- /compiler/natives/src/syscall/syscall_windows.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package syscall 4 | 5 | import "runtime" 6 | 7 | var minusOne = -1 8 | 9 | func Syscall(trap, nargs, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) { 10 | printWarning() 11 | return uintptr(minusOne), 0, EACCES 12 | } 13 | 14 | func Syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) { 15 | printWarning() 16 | return uintptr(minusOne), 0, EACCES 17 | } 18 | 19 | func Syscall9(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) { 20 | printWarning() 21 | return uintptr(minusOne), 0, EACCES 22 | } 23 | 24 | func Syscall12(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 uintptr) (r1, r2 uintptr, err Errno) { 25 | printWarning() 26 | return uintptr(minusOne), 0, EACCES 27 | } 28 | 29 | func Syscall15(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2 uintptr, err Errno) { 30 | printWarning() 31 | return uintptr(minusOne), 0, EACCES 32 | } 33 | 34 | func Syscall18(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18 uintptr) (r1, r2 uintptr, err Errno) { 35 | printWarning() 36 | return uintptr(minusOne), 0, EACCES 37 | } 38 | 39 | func loadlibrary(filename *uint16) (handle uintptr, err Errno) { 40 | printWarning() 41 | return uintptr(minusOne), EACCES 42 | } 43 | 44 | func getprocaddress(handle uintptr, procname *uint8) (proc uintptr, err Errno) { 45 | printWarning() 46 | return uintptr(minusOne), EACCES 47 | } 48 | 49 | func (d *LazyDLL) Load() error { 50 | return &DLLError{Msg: "system calls not available, see https://github.com/gopherjs/gopherjs/blob/master/doc/syscalls.md"} 51 | } 52 | 53 | func (p *LazyProc) Find() error { 54 | return &DLLError{Msg: "system calls not available, see https://github.com/gopherjs/gopherjs/blob/master/doc/syscalls.md"} 55 | } 56 | 57 | func getStdHandle(h int) (fd Handle) { 58 | if h == STD_OUTPUT_HANDLE { 59 | return 1 60 | } 61 | if h == STD_ERROR_HANDLE { 62 | return 2 63 | } 64 | return 0 65 | } 66 | 67 | func GetConsoleMode(console Handle, mode *uint32) (err error) { 68 | return DummyError{} 69 | } 70 | 71 | func WriteFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) { 72 | if handle == 1 || handle == 2 { 73 | printToConsole(buf) 74 | *done = uint32(len(buf)) 75 | return nil 76 | } 77 | printWarning() 78 | return nil 79 | } 80 | 81 | func ExitProcess(exitcode uint32) { 82 | runtime.Goexit() 83 | } 84 | 85 | func GetCommandLine() (cmd *uint16) { 86 | return 87 | } 88 | 89 | func CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, err error) { 90 | return nil, DummyError{} 91 | } 92 | 93 | func Getenv(key string) (value string, found bool) { 94 | return "", false 95 | } 96 | 97 | func GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, err error) { 98 | return 0, DummyError{} 99 | } 100 | 101 | type DummyError struct{} 102 | 103 | func (e DummyError) Error() string { 104 | return "" 105 | } 106 | -------------------------------------------------------------------------------- /compiler/natives/src/testing/example.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package testing 4 | 5 | import ( 6 | "fmt" 7 | "os" 8 | "strings" 9 | "time" 10 | ) 11 | 12 | func runExample(eg InternalExample) (ok bool) { 13 | if *chatty { 14 | fmt.Printf("=== RUN %s\n", eg.Name) 15 | } 16 | 17 | // Capture stdout. 18 | stdout := os.Stdout 19 | w, err := tempFile("." + eg.Name + ".stdout.") 20 | if err != nil { 21 | fmt.Fprintln(os.Stderr, err) 22 | os.Exit(1) 23 | } 24 | os.Stdout = w 25 | 26 | start := time.Now() 27 | ok = true 28 | 29 | // Clean up in a deferred call so we can recover if the example panics. 30 | defer func() { 31 | dstr := fmtDuration(time.Now().Sub(start)) 32 | 33 | // Close file, restore stdout, get output. 34 | w.Close() 35 | os.Stdout = stdout 36 | out, readFileErr := readFile(w.Name()) 37 | _ = os.Remove(w.Name()) 38 | if readFileErr != nil { 39 | fmt.Fprintf(os.Stderr, "testing: reading stdout file: %v\n", readFileErr) 40 | os.Exit(1) 41 | } 42 | 43 | var fail string 44 | err := recover() 45 | got := strings.TrimSpace(out) 46 | want := strings.TrimSpace(eg.Output) 47 | if eg.Unordered { 48 | if sortLines(got) != sortLines(want) && err == nil { 49 | fail = fmt.Sprintf("got:\n%s\nwant (unordered):\n%s\n", out, eg.Output) 50 | } 51 | } else { 52 | if got != want && err == nil { 53 | fail = fmt.Sprintf("got:\n%s\nwant:\n%s\n", got, want) 54 | } 55 | } 56 | if fail != "" || err != nil { 57 | fmt.Printf("--- FAIL: %s (%s)\n%s", eg.Name, dstr, fail) 58 | ok = false 59 | } else if *chatty { 60 | fmt.Printf("--- PASS: %s (%s)\n", eg.Name, dstr) 61 | } 62 | if err != nil { 63 | panic(err) 64 | } 65 | }() 66 | 67 | // Run example. 68 | eg.F() 69 | return 70 | } 71 | -------------------------------------------------------------------------------- /compiler/natives/src/testing/ioutil.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package testing 4 | 5 | import ( 6 | "bytes" 7 | "io" 8 | "os" 9 | "strconv" 10 | "sync" 11 | "time" 12 | ) 13 | 14 | var rand uint32 15 | var randmu sync.Mutex 16 | 17 | func reseed() uint32 { 18 | return uint32(time.Now().UnixNano() + int64(os.Getpid())) 19 | } 20 | 21 | func nextSuffix() string { 22 | randmu.Lock() 23 | r := rand 24 | if r == 0 { 25 | r = reseed() 26 | } 27 | r = r*1664525 + 1013904223 // constants from Numerical Recipes 28 | rand = r 29 | randmu.Unlock() 30 | return strconv.Itoa(int(1e9 + r%1e9))[1:] 31 | } 32 | 33 | // A functional copy of ioutil.TempFile, to avoid extra imports. 34 | func tempFile(prefix string) (f *os.File, err error) { 35 | dir := os.TempDir() 36 | 37 | nconflict := 0 38 | for i := 0; i < 10000; i++ { 39 | name := dir + string(os.PathSeparator) + prefix + nextSuffix() 40 | f, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600) 41 | if os.IsExist(err) { 42 | if nconflict++; nconflict > 10 { 43 | randmu.Lock() 44 | rand = reseed() 45 | randmu.Unlock() 46 | } 47 | continue 48 | } 49 | break 50 | } 51 | return 52 | } 53 | 54 | func readFile(filename string) (string, error) { 55 | f, err := os.Open(filename) 56 | if err != nil { 57 | return "", err 58 | } 59 | defer f.Close() 60 | var buf bytes.Buffer 61 | _, err = io.Copy(&buf, f) 62 | if err != nil { 63 | return "", err 64 | } 65 | return buf.String(), nil 66 | } 67 | -------------------------------------------------------------------------------- /compiler/natives/src/testing/testing.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package testing 4 | 5 | import "runtime" 6 | 7 | // The upstream callerName and frameSkip rely on runtime.Callers, 8 | // and panic if there are zero callers found. However, runtime.Callers 9 | // is not implemented for GopherJS at this time, so we can't use 10 | // that implementation. Use these stubs instead. 11 | func callerName(skip int) string { 12 | // Upstream callerName requires a functional runtime.Callers. 13 | // TODO: Implement if possible. 14 | return "" 15 | } 16 | 17 | func (*common) frameSkip(skip int) runtime.Frame { 18 | _, file, line, ok := runtime.Caller(skip) 19 | if !ok { 20 | return runtime.Frame{} 21 | } 22 | return runtime.Frame{ 23 | File: file, 24 | Line: line, 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /compiler/natives/src/text/template/template.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package template 4 | 5 | const maxExecDepth = 3000 6 | -------------------------------------------------------------------------------- /compiler/natives/src/time/time.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package time 4 | 5 | import ( 6 | "runtime" 7 | 8 | "github.com/gopherjs/gopherjs/js" 9 | ) 10 | 11 | // Make sure time.Unix func and time.Time struct it returns are always included with this package (despite DCE), 12 | // because they're needed for internalization/externalization of time.Time/Date. See issue https://github.com/gopherjs/gopherjs/issues/279. 13 | func init() { 14 | // avoid dead code elimination 15 | var _ Time = Unix(0, 0) 16 | } 17 | 18 | type runtimeTimer struct { 19 | i int32 20 | when int64 21 | period int64 22 | f func(interface{}, uintptr) 23 | arg interface{} 24 | timeout *js.Object 25 | active bool 26 | } 27 | 28 | func initLocal() { 29 | d := js.Global.Get("Date").New() 30 | s := d.String() 31 | i := indexByte(s, '(') 32 | j := indexByte(s, ')') 33 | if i == -1 || j == -1 { 34 | localLoc.name = "UTC" 35 | return 36 | } 37 | localLoc.name = s[i+1 : j] 38 | localLoc.zone = []zone{{localLoc.name, d.Call("getTimezoneOffset").Int() * -60, false}} 39 | } 40 | 41 | func runtimeNano() int64 { 42 | return js.Global.Get("Date").New().Call("getTime").Int64() * int64(Millisecond) 43 | } 44 | 45 | func now() (sec int64, nsec int32, mono int64) { 46 | n := runtimeNano() 47 | return n / int64(Second), int32(n % int64(Second)), n 48 | } 49 | 50 | func Sleep(d Duration) { 51 | c := make(chan struct{}) 52 | js.Global.Call("$setTimeout", js.InternalObject(func() { close(c) }), int(d/Millisecond)) 53 | <-c 54 | } 55 | 56 | func startTimer(t *runtimeTimer) { 57 | t.active = true 58 | diff := (t.when - runtimeNano()) / int64(Millisecond) 59 | if diff > 1<<31-1 { // math.MaxInt32 60 | return 61 | } 62 | if diff < 0 { 63 | diff = 0 64 | } 65 | t.timeout = js.Global.Call("$setTimeout", js.InternalObject(func() { 66 | t.active = false 67 | if t.period != 0 { 68 | t.when += t.period 69 | startTimer(t) 70 | } 71 | go t.f(t.arg, 0) 72 | }), diff+1) 73 | } 74 | 75 | func stopTimer(t *runtimeTimer) bool { 76 | js.Global.Call("clearTimeout", t.timeout) 77 | wasActive := t.active 78 | t.active = false 79 | return wasActive 80 | } 81 | 82 | func forceZipFileForTesting(zipOnly bool) { 83 | } 84 | 85 | var zoneSources = []string{ 86 | runtime.GOROOT() + "/lib/time/zoneinfo.zip", 87 | } 88 | 89 | // indexByte is copied from strings package to avoid importing it (since the real time package doesn't). 90 | func indexByte(s string, c byte) int { 91 | return js.InternalObject(s).Call("indexOf", js.Global.Get("String").Call("fromCharCode", c)).Int() 92 | } 93 | -------------------------------------------------------------------------------- /compiler/natives/src/unicode/unicode.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package unicode 4 | 5 | func to(_case int, r rune, caseRange []CaseRange) (mappedRune rune, foundMapping bool) { 6 | if _case < 0 || MaxCase <= _case { 7 | return ReplacementChar, false 8 | } 9 | lo := 0 10 | hi := len(caseRange) 11 | for lo < hi { 12 | m := lo + (hi-lo)/2 13 | cr := &caseRange[m] // performance critical for GopherJS: get address here instead of copying the CaseRange 14 | if rune(cr.Lo) <= r && r <= rune(cr.Hi) { 15 | delta := rune(cr.Delta[_case]) 16 | if delta > MaxRune { 17 | return rune(cr.Lo) + ((r-rune(cr.Lo))&^1 | rune(_case&1)), true 18 | } 19 | return r + delta, true 20 | } 21 | if r < rune(cr.Lo) { 22 | hi = m 23 | } else { 24 | lo = m + 1 25 | } 26 | } 27 | return r, false 28 | } 29 | -------------------------------------------------------------------------------- /compiler/prelude/formatpreludejs.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "go/build" 8 | "io/ioutil" 9 | "log" 10 | "os/exec" 11 | "path/filepath" 12 | "strings" 13 | ) 14 | 15 | func main() { 16 | if err := run(); err != nil { 17 | log.Fatalln(err) 18 | } 19 | } 20 | 21 | func run() error { 22 | bpkg, err := build.Import("github.com/gopherjs/gopherjs", ".", build.FindOnly) 23 | if err != nil { 24 | return fmt.Errorf("failed to locate path for github.com/gopherjs/gopherjs/compiler/prelude: %v", err) 25 | } 26 | 27 | preludeDir := filepath.Join(bpkg.Dir, "compiler", "prelude") 28 | 29 | args := []string{ 30 | filepath.Join(bpkg.Dir, "node_modules", ".bin", "prettier"), 31 | "--config", 32 | filepath.Join(preludeDir, "prettier_options.json"), 33 | "--write", 34 | } 35 | 36 | fis, err := ioutil.ReadDir(preludeDir) 37 | if err != nil { 38 | return fmt.Errorf("failed to list contents of %v: %v", preludeDir, err) 39 | } 40 | for _, fi := range fis { 41 | fn := fi.Name() 42 | if !strings.HasSuffix(fn, ".js") || strings.HasSuffix(fn, ".min.js") { 43 | continue 44 | } 45 | args = append(args, fn) 46 | } 47 | 48 | cmd := exec.Command(args[0], args[1:]...) 49 | 50 | out, err := cmd.CombinedOutput() 51 | if err != nil { 52 | return fmt.Errorf("failed to run %v: %v\n%s", strings.Join(args, " "), err, string(out)) 53 | } 54 | 55 | return nil 56 | } 57 | -------------------------------------------------------------------------------- /compiler/prelude/generate.go: -------------------------------------------------------------------------------- 1 | package prelude 2 | 3 | //go:generate go run formatpreludejs.go 4 | //go:generate go run genprelude.go 5 | -------------------------------------------------------------------------------- /compiler/prelude/genprelude.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | package main 4 | 5 | import ( 6 | "bytes" 7 | "fmt" 8 | "go/build" 9 | "io/ioutil" 10 | "log" 11 | "os/exec" 12 | "path/filepath" 13 | "strings" 14 | ) 15 | 16 | const ( 17 | fn = "prelude.go" 18 | minFn = "prelude_min.go" 19 | ) 20 | 21 | func main() { 22 | if err := run(); err != nil { 23 | log.Fatalln(err) 24 | } 25 | } 26 | 27 | func run() error { 28 | bpkg, err := build.Import("github.com/gopherjs/gopherjs", ".", build.FindOnly) 29 | if err != nil { 30 | return fmt.Errorf("failed to locate path for github.com/gopherjs/gopherjs: %v", err) 31 | } 32 | 33 | preludeDir := filepath.Join(bpkg.Dir, "compiler", "prelude") 34 | 35 | files := []string{ 36 | "prelude.js", 37 | "numeric.js", 38 | "types.js", 39 | "goroutines.js", 40 | "jsmapping.js", 41 | } 42 | 43 | prelude := new(bytes.Buffer) 44 | 45 | for _, f := range files { 46 | p := filepath.Join(preludeDir, f) 47 | out, err := ioutil.ReadFile(p) 48 | if err != nil { 49 | return fmt.Errorf("failed to read from %v: %v", p, err) 50 | } 51 | if _, err := prelude.Write(out); err != nil { 52 | return fmt.Errorf("failed to append prelude: %v", err) 53 | } 54 | } 55 | 56 | args := append([]string{ 57 | filepath.Join(bpkg.Dir, "node_modules", ".bin", "uglifyjs"), 58 | "--config-file", 59 | filepath.Join(preludeDir, "uglifyjs_options.json"), 60 | }, files...) 61 | 62 | stderr := new(bytes.Buffer) 63 | 64 | cmd := exec.Command(args[0], args[1:]...) 65 | cmd.Stderr = stderr 66 | 67 | minout, err := cmd.Output() 68 | if err != nil { 69 | return fmt.Errorf("failed to run %v: %v\n%s", strings.Join(args, " "), err, stderr.Bytes()) 70 | } 71 | 72 | err = writeOutput("prelude.go", ""+ 73 | "// Prelude is the GopherJS JavaScript interop layer.\n"+ 74 | "const Prelude = %q", prelude.Bytes()) 75 | 76 | if err != nil { 77 | return err 78 | } 79 | 80 | err = writeOutput("prelude_min.go", ""+ 81 | "// Minified is an uglifyjs-minified version of Prelude.\n"+ 82 | "const Minified = %q", minout) 83 | 84 | return err 85 | } 86 | 87 | func writeOutput(fn string, format string, byts []byte) error { 88 | content := fmt.Sprintf("// Code generated by genprelude; DO NOT EDIT.\n\n"+ 89 | "package prelude\n\n"+format+"\n", byts) 90 | 91 | if err := ioutil.WriteFile(fn, []byte(content), 0644); err != nil { 92 | return fmt.Errorf("failed to write to %v: %v", fn, err) 93 | } 94 | 95 | return nil 96 | } 97 | -------------------------------------------------------------------------------- /compiler/prelude/numeric.js: -------------------------------------------------------------------------------- 1 | var $min = Math.min; 2 | var $mod = function(x, y) { 3 | return x % y; 4 | }; 5 | var $parseInt = parseInt; 6 | var $parseFloat = function(f) { 7 | if (f !== undefined && f !== null && f.constructor === Number) { 8 | return f; 9 | } 10 | return parseFloat(f); 11 | }; 12 | 13 | var $froundBuf = new Float32Array(1); 14 | var $fround = 15 | Math.fround || 16 | function(f) { 17 | $froundBuf[0] = f; 18 | return $froundBuf[0]; 19 | }; 20 | 21 | var $imul = 22 | Math.imul || 23 | function(a, b) { 24 | var ah = (a >>> 16) & 0xffff; 25 | var al = a & 0xffff; 26 | var bh = (b >>> 16) & 0xffff; 27 | var bl = b & 0xffff; 28 | return (al * bl + (((ah * bl + al * bh) << 16) >>> 0)) >> 0; 29 | }; 30 | 31 | var $floatKey = function(f) { 32 | if (f !== f) { 33 | $idCounter++; 34 | return "NaN$" + $idCounter; 35 | } 36 | return String(f); 37 | }; 38 | 39 | var $flatten64 = function(x) { 40 | return x.$high * 4294967296 + x.$low; 41 | }; 42 | 43 | var $shiftLeft64 = function(x, y) { 44 | if (y === 0) { 45 | return x; 46 | } 47 | if (y < 32) { 48 | return new x.constructor((x.$high << y) | (x.$low >>> (32 - y)), (x.$low << y) >>> 0); 49 | } 50 | if (y < 64) { 51 | return new x.constructor(x.$low << (y - 32), 0); 52 | } 53 | return new x.constructor(0, 0); 54 | }; 55 | 56 | var $shiftRightInt64 = function(x, y) { 57 | if (y === 0) { 58 | return x; 59 | } 60 | if (y < 32) { 61 | return new x.constructor(x.$high >> y, ((x.$low >>> y) | (x.$high << (32 - y))) >>> 0); 62 | } 63 | if (y < 64) { 64 | return new x.constructor(x.$high >> 31, (x.$high >> (y - 32)) >>> 0); 65 | } 66 | if (x.$high < 0) { 67 | return new x.constructor(-1, 4294967295); 68 | } 69 | return new x.constructor(0, 0); 70 | }; 71 | 72 | var $shiftRightUint64 = function(x, y) { 73 | if (y === 0) { 74 | return x; 75 | } 76 | if (y < 32) { 77 | return new x.constructor(x.$high >>> y, ((x.$low >>> y) | (x.$high << (32 - y))) >>> 0); 78 | } 79 | if (y < 64) { 80 | return new x.constructor(0, x.$high >>> (y - 32)); 81 | } 82 | return new x.constructor(0, 0); 83 | }; 84 | 85 | var $mul64 = function(x, y) { 86 | var high = 0, 87 | low = 0; 88 | if ((y.$low & 1) !== 0) { 89 | high = x.$high; 90 | low = x.$low; 91 | } 92 | for (var i = 1; i < 32; i++) { 93 | if ((y.$low & (1 << i)) !== 0) { 94 | high += (x.$high << i) | (x.$low >>> (32 - i)); 95 | low += (x.$low << i) >>> 0; 96 | } 97 | } 98 | for (var i = 0; i < 32; i++) { 99 | if ((y.$high & (1 << i)) !== 0) { 100 | high += x.$low << i; 101 | } 102 | } 103 | return new x.constructor(high, low); 104 | }; 105 | 106 | var $div64 = function(x, y, returnRemainder) { 107 | if (y.$high === 0 && y.$low === 0) { 108 | $throwRuntimeError("integer divide by zero"); 109 | } 110 | 111 | var s = 1; 112 | var rs = 1; 113 | 114 | var xHigh = x.$high; 115 | var xLow = x.$low; 116 | if (xHigh < 0) { 117 | s = -1; 118 | rs = -1; 119 | xHigh = -xHigh; 120 | if (xLow !== 0) { 121 | xHigh--; 122 | xLow = 4294967296 - xLow; 123 | } 124 | } 125 | 126 | var yHigh = y.$high; 127 | var yLow = y.$low; 128 | if (y.$high < 0) { 129 | s *= -1; 130 | yHigh = -yHigh; 131 | if (yLow !== 0) { 132 | yHigh--; 133 | yLow = 4294967296 - yLow; 134 | } 135 | } 136 | 137 | var high = 0, 138 | low = 0, 139 | n = 0; 140 | while (yHigh < 2147483648 && (xHigh > yHigh || (xHigh === yHigh && xLow > yLow))) { 141 | yHigh = ((yHigh << 1) | (yLow >>> 31)) >>> 0; 142 | yLow = (yLow << 1) >>> 0; 143 | n++; 144 | } 145 | for (var i = 0; i <= n; i++) { 146 | high = (high << 1) | (low >>> 31); 147 | low = (low << 1) >>> 0; 148 | if (xHigh > yHigh || (xHigh === yHigh && xLow >= yLow)) { 149 | xHigh = xHigh - yHigh; 150 | xLow = xLow - yLow; 151 | if (xLow < 0) { 152 | xHigh--; 153 | xLow += 4294967296; 154 | } 155 | low++; 156 | if (low === 4294967296) { 157 | high++; 158 | low = 0; 159 | } 160 | } 161 | yLow = ((yLow >>> 1) | (yHigh << (32 - 1))) >>> 0; 162 | yHigh = yHigh >>> 1; 163 | } 164 | 165 | if (returnRemainder) { 166 | return new x.constructor(xHigh * rs, xLow * rs); 167 | } 168 | return new x.constructor(high * s, low * s); 169 | }; 170 | 171 | var $divComplex = function(n, d) { 172 | var ninf = n.$real === Infinity || n.$real === -Infinity || n.$imag === Infinity || n.$imag === -Infinity; 173 | var dinf = d.$real === Infinity || d.$real === -Infinity || d.$imag === Infinity || d.$imag === -Infinity; 174 | var nnan = !ninf && (n.$real !== n.$real || n.$imag !== n.$imag); 175 | var dnan = !dinf && (d.$real !== d.$real || d.$imag !== d.$imag); 176 | if (nnan || dnan) { 177 | return new n.constructor(NaN, NaN); 178 | } 179 | if (ninf && !dinf) { 180 | return new n.constructor(Infinity, Infinity); 181 | } 182 | if (!ninf && dinf) { 183 | return new n.constructor(0, 0); 184 | } 185 | if (d.$real === 0 && d.$imag === 0) { 186 | if (n.$real === 0 && n.$imag === 0) { 187 | return new n.constructor(NaN, NaN); 188 | } 189 | return new n.constructor(Infinity, Infinity); 190 | } 191 | var a = Math.abs(d.$real); 192 | var b = Math.abs(d.$imag); 193 | if (a <= b) { 194 | var ratio = d.$real / d.$imag; 195 | var denom = d.$real * ratio + d.$imag; 196 | return new n.constructor((n.$real * ratio + n.$imag) / denom, (n.$imag * ratio - n.$real) / denom); 197 | } 198 | var ratio = d.$imag / d.$real; 199 | var denom = d.$imag * ratio + d.$real; 200 | return new n.constructor((n.$imag * ratio + n.$real) / denom, (n.$imag - n.$real * ratio) / denom); 201 | }; 202 | -------------------------------------------------------------------------------- /compiler/prelude/prettier_options.json: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 1000000, 3 | "trailingComma": "es5" 4 | } 5 | -------------------------------------------------------------------------------- /compiler/prelude/uglifyjs_options.json: -------------------------------------------------------------------------------- 1 | { 2 | "compress": { 3 | "arrows": true, 4 | "booleans": true, 5 | "collapse_vars": true, 6 | "comparisons": true, 7 | "computed_props": true, 8 | "conditionals": true, 9 | "dead_code": true, 10 | "drop_console": false, 11 | "drop_debugger": true, 12 | "ecma": 5, 13 | "evaluate": true, 14 | "expression": false, 15 | "global_defs": {}, 16 | "hoist_funs": false, 17 | "hoist_props": true, 18 | "hoist_vars": false, 19 | "ie8": false, 20 | "if_return": true, 21 | "inline": true, 22 | "join_vars": true, 23 | "keep_classnames": false, 24 | "keep_fargs": true, 25 | "keep_fnames": false, 26 | "keep_infinity": false, 27 | "loops": true, 28 | "negate_iife": true, 29 | "passes": 1, 30 | "properties": true, 31 | "pure_funcs": null, 32 | "pure_getters": "strict", 33 | "reduce_funcs": true, 34 | "reduce_vars": true, 35 | "sequences": true, 36 | "side_effects": true, 37 | "switches": true, 38 | "top_retain": null, 39 | "toplevel": false, 40 | "typeofs": true, 41 | "unsafe": false, 42 | "unsafe_Function": false, 43 | "unsafe_arrows": false, 44 | "unsafe_comps": false, 45 | "unsafe_math": false, 46 | "unsafe_methods": false, 47 | "unsafe_proto": false, 48 | "unsafe_regexp": false, 49 | "unsafe_undefined": false, 50 | "unused": true, 51 | "warnings": false 52 | }, 53 | "mangle": { 54 | "eval": false, 55 | "ie8": false, 56 | "keep_classnames": false, 57 | "keep_fnames": false, 58 | "properties": false, 59 | "reserved": [], 60 | "safari10": false, 61 | "toplevel": false 62 | }, 63 | "output": { 64 | "ascii_only": false, 65 | "beautify": false, 66 | "bracketize": false, 67 | "comments": "/@license|@preserve|^!/", 68 | "ecma": 5, 69 | "ie8": false, 70 | "indent_level": 4, 71 | "indent_start": 0, 72 | "inline_script": true, 73 | "keep_quoted_props": false, 74 | "max_line_len": false, 75 | "preamble": null, 76 | "preserve_line": false, 77 | "quote_keys": false, 78 | "quote_style": 0, 79 | "safari10": false, 80 | "semicolons": true, 81 | "shebang": true, 82 | "source_map": null, 83 | "webkit": false, 84 | "width": 80, 85 | "wrap_iife": false 86 | }, 87 | "parse": { 88 | "bare_returns": false, 89 | "ecma": 8, 90 | "expression": false, 91 | "filename": null, 92 | "html5_comments": true, 93 | "shebang": true, 94 | "strict": false, 95 | "toplevel": null 96 | }, 97 | "wrap": false 98 | } 99 | -------------------------------------------------------------------------------- /compiler/typesutil/typesutil.go: -------------------------------------------------------------------------------- 1 | package typesutil 2 | 3 | import "go/types" 4 | 5 | func IsJsPackage(pkg *types.Package) bool { 6 | return pkg != nil && pkg.Path() == "github.com/gopherjs/gopherjs/js" 7 | } 8 | 9 | func IsJsObject(t types.Type) bool { 10 | ptr, isPtr := t.(*types.Pointer) 11 | if !isPtr { 12 | return false 13 | } 14 | named, isNamed := ptr.Elem().(*types.Named) 15 | return isNamed && IsJsPackage(named.Obj().Pkg()) && named.Obj().Name() == "Object" 16 | } 17 | -------------------------------------------------------------------------------- /compiler/version_check.go: -------------------------------------------------------------------------------- 1 | // +build go1.12 2 | // +build !go1.13 3 | 4 | package compiler 5 | 6 | const ___GOPHERJS_REQUIRES_GO_VERSION_1_12___ = true 7 | 8 | // Version is the GopherJS compiler version string. 9 | const Version = "1.12" 10 | -------------------------------------------------------------------------------- /doc/packages.md: -------------------------------------------------------------------------------- 1 | # Supported Packages 2 | 3 | On each commit, Circle CI automatically compiles all supported packages with GopherJS and runs their tests: 4 | 5 | [![Circle CI](https://circleci.com/gh/gopherjs/gopherjs.svg?style=svg)](https://circleci.com/gh/gopherjs/gopherjs) 6 | 7 | Name | Supported | Comment 8 | ------------------ | ------------ | ---------------------------------------------------------------------------------- 9 | archive | | 10 | -- tar | ✅ yes | 11 | -- zip | ✅ yes | 12 | bufio | ✅ yes | 13 | builtin | ✅ yes | 14 | bytes | ✅ yes | 15 | compress | | 16 | -- bzip2 | ✅ yes | 17 | -- flate | ✅ yes | 18 | -- gzip | ✅ yes | 19 | -- lzw | ✅ yes | 20 | -- zlib | ✅ yes | 21 | container | | 22 | -- heap | ✅ yes | 23 | -- list | ✅ yes | 24 | -- ring | ✅ yes | 25 | crypto | | 26 | -- aes | ✅ yes | 27 | -- cipher | ✅ yes | 28 | -- des | ✅ yes | 29 | -- dsa | ✅ yes | 30 | -- ecdsa | ✅ yes | 31 | -- elliptic | ✅ yes | 32 | -- hmac | ✅ yes | 33 | -- md5 | ✅ yes | 34 | -- rand | ✅ yes | 35 | -- rc4 | ✅ yes | 36 | -- rsa | ✅ yes | 37 | -- sha1 | ✅ yes | 38 | -- sha256 | ✅ yes | 39 | -- sha512 | ✅ yes | 40 | -- subtle | ✅ yes | 41 | -- tls | ❌ no | 42 | -- x509 | ✅ yes | 43 | -- -- pkix | ✅ yes | 44 | database | | 45 | -- sql | ✅ yes | 46 | -- -- driver | ✅ yes | 47 | debug | | 48 | -- dwarf | ✅ yes | 49 | -- elf | ✅ yes | 50 | -- gosym | ☑️ partially | on binaries generated by gc 51 | -- macho | ✅ yes | 52 | -- pe | ✅ yes | 53 | encoding | | 54 | -- ascii85 | ✅ yes | 55 | -- asn1 | ✅ yes | 56 | -- base32 | ✅ yes | 57 | -- base64 | ✅ yes | 58 | -- binary | ✅ yes | 59 | -- csv | ✅ yes | 60 | -- gob | ✅ yes | 61 | -- hex | ✅ yes | 62 | -- json | ✅ yes | 63 | -- pem | ✅ yes | 64 | -- xml | ✅ yes | 65 | errors | ✅ yes | 66 | expvar | ✅ yes | 67 | flag | ✅ yes | 68 | fmt | ✅ yes | 69 | go | | 70 | -- ast | ✅ yes | 71 | -- build | ❌ no | 72 | -- constant | ✅ yes | 73 | -- doc | ✅ yes | 74 | -- format | ✅ yes | 75 | -- importer | ❌ no | 76 | -- parser | ✅ yes | 77 | -- printer | ✅ yes | 78 | -- scanner | ✅ yes | 79 | -- token | ✅ yes | 80 | -- types | ❌ no | 81 | hash | | 82 | -- adler32 | ✅ yes | 83 | -- crc32 | ✅ yes | 84 | -- crc64 | ✅ yes | 85 | -- fnv | ✅ yes | 86 | html | ✅ yes | 87 | -- template | ✅ yes | 88 | image | ✅ yes | 89 | -- color | ✅ yes | 90 | -- -- palette | ✅ yes | 91 | -- draw | ✅ yes | 92 | -- gif | ✅ yes | 93 | -- jpeg | ✅ yes | 94 | -- png | ✅ yes | 95 | index | | 96 | -- suffixarray | ✅ yes | 97 | io | ✅ yes | 98 | -- ioutil | ✅ yes | 99 | log | ✅ yes | 100 | -- syslog | ❌ no | 101 | math | ✅ yes | 102 | -- big | ✅ yes | 103 | -- bits | ✅ yes | 104 | -- cmplx | ✅ yes | 105 | -- rand | ✅ yes | 106 | mime | ✅ yes | 107 | -- multipart | ✅ yes | 108 | -- quotedprintable | ✅ yes | 109 | net | ❌ no | 110 | -- http | ☑️ partially | client only, emulated via Fetch/XMLHttpRequest APIs;
node.js requires polyfill 111 | -- -- cgi | ❌ no | 112 | -- -- cookiejar | ✅ yes | 113 | -- -- fcgi | ✅ yes | 114 | -- -- httptest | ☑️ partially | 115 | -- -- httputil | ☑️ partially | 116 | -- -- pprof | ❌ no | 117 | -- mail | ✅ yes | 118 | -- rpc | ☑️ partially | data structures only (no net) 119 | -- -- jsonrpc | ✅ yes | 120 | -- smtp | ☑️ partially | data structures only (no net) 121 | -- textproto | ✅ yes | 122 | -- url | ✅ yes | 123 | os | ☑️ partially | node.js only 124 | -- exec | ☑️ partially | node.js only 125 | -- signal | ☑️ partially | node.js only 126 | -- user | ☑️ partially | node.js only 127 | path | ✅ yes | 128 | -- filepath | ✅ yes | 129 | plugin | ❌ no | 130 | reflect | ✅ yes | except StructOf (pending) 131 | regexp | ✅ yes | 132 | -- syntax | ✅ yes | 133 | runtime | ☑️ partially | SetMutexProfileFraction, SetFinalizer, ReadMemStats, Callers, CallersFrames unsupported 134 | -- cgo | ❌ no | 135 | -- debug | ❌ no | 136 | -- pprof | ❌ no | 137 | -- race | ❌ no | 138 | -- trace | ❌ no | 139 | sort | ✅ yes | 140 | strconv | ✅ yes | 141 | strings | ✅ yes | 142 | sync | ✅ yes | 143 | -- atomic | ✅ yes | 144 | syscall | ☑️ partially | node.js only 145 | testing | ☑️ partially | AllocsPerRun unsupported 146 | -- iotest | ✅ yes | 147 | -- quick | ✅ yes | 148 | text | | 149 | -- scanner | ✅ yes | 150 | -- tabwriter | ✅ yes | 151 | -- template | ✅ yes | 152 | -- -- parse | ✅ yes | 153 | time | ✅ yes | UTC and Local only (see [issue](https://github.com/gopherjs/gopherjs/issues/64)) 154 | unicode | ✅ yes | 155 | -- utf16 | ✅ yes | 156 | -- utf8 | ✅ yes | 157 | unsafe | ❌ no | 158 | -------------------------------------------------------------------------------- /doc/syscalls.md: -------------------------------------------------------------------------------- 1 | System Calls 2 | ------------ 3 | 4 | System calls are the bridge between your application and your operating system. They are used whenever you access something outside of your application's memory, for example when you write to the console, when you read or write files or when you access the network. In Go, system calls are mostly used by the `os` package, hence the name. When using GopherJS you need to consider if system calls are available or not. 5 | 6 | ### Output redirection to console 7 | 8 | If system calls are not available in your environment (see below), then a special redirection of `os.Stdout` and `os.Stderr` is applied. It buffers a line until it is terminated by a line break and then prints it via JavaScript's `console.log` to your browser's JavaScript console or your system console. That way, `fmt.Println` etc. work as expected, even if system calls are not available. 9 | 10 | ### In Browser 11 | 12 | The JavaScript environment of a web browser is completely isolated from your operating system to protect your machine. You don't want any web page to read or write files on your disk without your consent. That is why system calls are not and will never be available when running your code in a web browser. 13 | 14 | ### Node.js on Linux and macOS 15 | 16 | GopherJS has support for system calls on Linux and macOS. Before running your code with Node.js, you need to install the system calls module. The module is compatible with Node.js version 10.0.0 (or newer). If you want to use an older version you can opt to not install the module, but then system calls are not available. 17 | 18 | Compile and install the module with: 19 | 20 | ``` 21 | cd $GOPATH/src/github.com/gopherjs/gopherjs/node-syscall/ 22 | npm install --global node-gyp 23 | node-gyp rebuild 24 | mkdir -p ~/.node_libraries/ 25 | cp build/Release/syscall.node ~/.node_libraries/syscall.node 26 | ``` 27 | 28 | ### Node.js on Windows 29 | 30 | When running your code with Node.js on Windows, it is theoretically possible to use system calls. To do so, you would need a special Node.js module that provides direct access to system calls. However, since the interface is quite different from the one used on Linux and macOS, the system calls module included in GopherJS currently does not support Windows. Sorry. Get in contact if you feel like you want to change this situation. 31 | 32 | ### Caveats 33 | 34 | Note that even with syscalls enabled in Node.js, some programs may not behave as expected due to the fact that the current implementation blocks other goroutines during a syscall, which can lead to a deadlock in some situations. This is not considered a bug, as it is considered sufficient for most test cases (which is all Node.js should be used for). Get in contact if you feel like you want to change this situation. 35 | -------------------------------------------------------------------------------- /genmodstubbs.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | package main 4 | 5 | import ( 6 | "bytes" 7 | "encoding/json" 8 | "flag" 9 | "log" 10 | "os" 11 | "os/exec" 12 | "path/filepath" 13 | "strings" 14 | "text/template" 15 | 16 | "github.com/rogpeppe/go-internal/module" 17 | ) 18 | 19 | func main() { 20 | flag.Parse() 21 | 22 | gmt := exec.Command("go", "mod", "tidy") 23 | if err := gmt.Run(); err != nil { 24 | log.Fatalf("failed to run %v: %v\n%s", strings.Join(gmt.Args, " "), err, errToBytes(err)) 25 | } 26 | 27 | gme := exec.Command("go", "mod", "edit", "-json") 28 | gme.Stderr = new(bytes.Buffer) 29 | 30 | out, err := gme.Output() 31 | if err != nil { 32 | log.Fatalf("failed to run %v: %v\n%s", strings.Join(gme.Args, " "), err, errToBytes(err)) 33 | } 34 | 35 | type mod struct { 36 | Path string 37 | Version string 38 | } 39 | 40 | var goMod struct { 41 | Require []mod 42 | } 43 | 44 | if err := json.Unmarshal(out, &goMod); err != nil { 45 | log.Fatalf("failed to unmarshal: %v\n%s", err, out) 46 | } 47 | 48 | // add in gopherjs v0.0.0 to satisfy our redirect 49 | goMod.Require = append(goMod.Require, mod{ 50 | Path: "github.com/gopherjs/gopherjs", 51 | Version: "v0.0.0", 52 | }) 53 | 54 | dirCmd := exec.Command("go", "list", "-m", "-f={{.Dir}}") 55 | out, err = dirCmd.Output() 56 | if err != nil { 57 | log.Fatalf("failed to run %v: %v\n%s", strings.Join(dirCmd.Args, " "), err, errToBytes(err)) 58 | } 59 | 60 | dir := strings.TrimSpace(string(out)) 61 | mods := filepath.Join(dir, "testdata", "mod") 62 | 63 | curr, err := filepath.Glob(filepath.Join(mods, "*")) 64 | if err != nil { 65 | log.Fatalf("failed to glob current mod files: %v", err) 66 | } 67 | 68 | for _, c := range curr { 69 | base := filepath.Base(c) 70 | if strings.HasPrefix(base, "example.com") { 71 | continue 72 | } 73 | 74 | if err := os.Remove(c); err != nil { 75 | log.Fatalf("failed to remove %v: %v", c, err) 76 | } 77 | } 78 | 79 | if err := os.MkdirAll(mods, 0755); err != nil { 80 | log.Fatalf("failed to create directory %v: %v", mods, err) 81 | } 82 | 83 | tmpl := template.Must(template.New("tmpl").Parse(` 84 | module {{.Path}}@{{.Version}} 85 | 86 | -- .mod -- 87 | module "{{.Path}}" 88 | 89 | -- .info -- 90 | {"Version":"{{.Version}}","Time":"2018-05-06T08:24:08Z"} 91 | `[1:])) 92 | 93 | for _, r := range goMod.Require { 94 | enc, err := module.EncodePath(r.Path) 95 | if err != nil { 96 | log.Fatalf("failed to encode path %q: %v", r.Path, err) 97 | } 98 | ver, err := module.EncodeVersion(r.Version) 99 | if err != nil { 100 | log.Fatalf("failed to encode version %q: %v", r.Version, err) 101 | } 102 | 103 | prefix := strings.Replace(enc, "/", "_", -1) 104 | name := filepath.Join(mods, prefix+"_"+ver+".txt") 105 | f, err := os.Create(name) 106 | if err != nil { 107 | log.Fatalf("failed to create %v: %v", name, err) 108 | } 109 | 110 | if err := tmpl.Execute(f, r); err != nil { 111 | log.Fatalf("failed to execute template for %v: %v", name, err) 112 | } 113 | 114 | if err := f.Close(); err != nil { 115 | log.Fatalf("failed to close %v: %v", name, err) 116 | } 117 | } 118 | } 119 | 120 | func errToBytes(err error) []byte { 121 | if ee, ok := err.(*exec.ExitError); ok { 122 | return ee.Stderr 123 | } 124 | 125 | return nil 126 | } 127 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/gopherjs/gopherjs 2 | 3 | require ( 4 | github.com/fsnotify/fsnotify v1.4.7 5 | github.com/inconshreveable/mousetrap v1.0.0 // indirect 6 | github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86 7 | github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab 8 | github.com/rogpeppe/go-internal v1.0.1-alpha.1 9 | github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e 10 | github.com/shurcooL/httpfs v0.0.0-20181222201310-74dc9339e414 11 | github.com/shurcooL/vfsgen v0.0.0-20180915214035-33ae1944be3f 12 | github.com/spf13/cobra v0.0.3 13 | github.com/spf13/pflag v1.0.1 14 | golang.org/x/crypto v0.0.0-20180807104621-f027049dab0a 15 | golang.org/x/sys v0.0.0-20180807162357-acbc56fc7007 16 | golang.org/x/tools v0.0.0-20190308142131-b40df0fb21c3 17 | ) 18 | 19 | // branch: master (latest) 20 | replace github.com/shurcooL/vfsgen => github.com/myitcv/vfsgen v0.0.1 21 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= 2 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 3 | github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= 4 | github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= 5 | github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= 6 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 7 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 8 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 9 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 10 | github.com/myitcv/vfsgen v0.0.1 h1:VR3+FgXoQ6Sa9pOVXFHb0vEx0hVC6CNf6j2aavJf40s= 11 | github.com/myitcv/vfsgen v0.0.1/go.mod h1:mpzzquL5p6afXJW1DpBzsFUsy3LqGoaYDkz1fZKjbLk= 12 | github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86 h1:D6paGObi5Wud7xg83MaEFyjxQB1W5bz5d0IFppr+ymk= 13 | github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= 14 | github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab h1:eFXv9Nu1lGbrNbj619aWwZfVF5HBrm9Plte8aNptuTI= 15 | github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= 16 | github.com/rogpeppe/go-internal v1.0.1-alpha.1 h1:NGPDe06RaK5iQFZkqFMNb986UARfoHc9FLyWI7b6+aQ= 17 | github.com/rogpeppe/go-internal v1.0.1-alpha.1/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 18 | github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e h1:MZM7FHLqUHYI0Y/mQAt3d2aYa0SiNms/hFqC9qJYolM= 19 | github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= 20 | github.com/shurcooL/httpfs v0.0.0-20181222201310-74dc9339e414 h1:IYVb70m/qpJGjyZV2S4qbdSDnsMl+w9nsQ2iQedf1HI= 21 | github.com/shurcooL/httpfs v0.0.0-20181222201310-74dc9339e414/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= 22 | github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= 23 | github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8= 24 | github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= 25 | github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4= 26 | github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 27 | golang.org/x/crypto v0.0.0-20180807104621-f027049dab0a h1:PulT0Y50PcfTWomfsD39bSQyVrjjWdIuJKfyR4nOCJw= 28 | golang.org/x/crypto v0.0.0-20180807104621-f027049dab0a/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 29 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 30 | golang.org/x/sys v0.0.0-20180807162357-acbc56fc7007 h1:UnHxDq9ldm4vol94wlSWDF3SU4IyC8IWVWtg266CzoY= 31 | golang.org/x/sys v0.0.0-20180807162357-acbc56fc7007/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 32 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 33 | golang.org/x/tools v0.0.0-20190307163923-6a08e3108db3 h1:2oZsfYnKfYzL4I57uYiRFsUf0bqlLkiuw8nnj3+voUA= 34 | golang.org/x/tools v0.0.0-20190307163923-6a08e3108db3/go.mod h1:25r3+/G6/xytQM8iWZKq3Hn0kr0rgFKPUNVEL/dr3z4= 35 | golang.org/x/tools v0.0.0-20190308142131-b40df0fb21c3 h1:GPRyd2anWNtiuo1j4VS6+tIW4Qu5bCWKy4sjzUf/3oI= 36 | golang.org/x/tools v0.0.0-20190308142131-b40df0fb21c3/go.mod h1:25r3+/G6/xytQM8iWZKq3Hn0kr0rgFKPUNVEL/dr3z4= 37 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= 38 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 39 | gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8= 40 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 41 | -------------------------------------------------------------------------------- /internal/sysutil/sysutil.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | 3 | // Package sysutil contains system-specific utilities. 4 | package sysutil 5 | 6 | import "golang.org/x/sys/unix" 7 | 8 | // RlimitStack reports the current stack size limit in bytes. 9 | func RlimitStack() (cur uint64, err error) { 10 | var r unix.Rlimit 11 | err = unix.Getrlimit(unix.RLIMIT_STACK, &r) 12 | return uint64(r.Cur), err // Type conversion because Cur is one of uint64, int64 depending on unix flavor. 13 | } 14 | -------------------------------------------------------------------------------- /internal/sysutil/sysutil_windows.go: -------------------------------------------------------------------------------- 1 | package sysutil 2 | 3 | import "errors" 4 | 5 | func RlimitStack() (uint64, error) { 6 | return 0, errors.New("RlimitStack is not implemented on Windows") 7 | } 8 | -------------------------------------------------------------------------------- /node-syscall/binding.gyp: -------------------------------------------------------------------------------- 1 | { 2 | 'targets': [ 3 | { 4 | 'target_name': 'syscall', 5 | 'sources': [ 'syscall.cc' ] 6 | } 7 | ] 8 | } -------------------------------------------------------------------------------- /node-syscall/syscall.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace v8; 9 | 10 | #if NODE_MAJOR_VERSION == 0 11 | #define ARRAY_BUFFER_DATA_OFFSET 23 12 | #else 13 | #define ARRAY_BUFFER_DATA_OFFSET 31 14 | #endif 15 | 16 | intptr_t toNative(Local value) { 17 | if (value.IsEmpty()) { 18 | return 0; 19 | } 20 | if (value->IsArrayBufferView()) { 21 | Local view = Local::Cast(value); 22 | return *reinterpret_cast(*reinterpret_cast(*view->Buffer()) + ARRAY_BUFFER_DATA_OFFSET) + view->ByteOffset(); // ugly hack, because of https://codereview.chromium.org/25221002 23 | } 24 | if (value->IsArray()) { 25 | Local array = Local::Cast(value); 26 | intptr_t* native = reinterpret_cast(malloc(array->Length() * sizeof(intptr_t))); // TODO memory leak 27 | for (uint32_t i = 0; i < array->Length(); i++) { 28 | native[i] = toNative(array->Get(i)); 29 | } 30 | return reinterpret_cast(native); 31 | } 32 | return static_cast(static_cast(value->ToInteger()->Value())); 33 | } 34 | 35 | void Syscall(const FunctionCallbackInfo& info) { 36 | int trap = info[0]->ToInteger()->Value(); 37 | int r1 = 0, r2 = 0; 38 | switch (trap) { 39 | case SYS_fork: 40 | r1 = fork(); 41 | break; 42 | case SYS_pipe: 43 | int fd[2]; 44 | r1 = pipe(fd); 45 | if (r1 == 0) { 46 | r1 = fd[0]; 47 | r2 = fd[1]; 48 | } 49 | break; 50 | default: 51 | r1 = syscall( 52 | trap, 53 | toNative(info[1]), 54 | toNative(info[2]), 55 | toNative(info[3]) 56 | ); 57 | break; 58 | } 59 | int err = 0; 60 | if (r1 < 0) { 61 | err = errno; 62 | } 63 | Isolate* isolate = info.GetIsolate(); 64 | Local res = Array::New(isolate, 3); 65 | res->Set(0, Integer::New(isolate, r1)); 66 | res->Set(1, Integer::New(isolate, r2)); 67 | res->Set(2, Integer::New(isolate, err)); 68 | info.GetReturnValue().Set(res); 69 | } 70 | 71 | void Syscall6(const FunctionCallbackInfo& info) { 72 | int r = syscall( 73 | info[0]->ToInteger()->Value(), 74 | toNative(info[1]), 75 | toNative(info[2]), 76 | toNative(info[3]), 77 | toNative(info[4]), 78 | toNative(info[5]), 79 | toNative(info[6]) 80 | ); 81 | int err = 0; 82 | if (r < 0) { 83 | err = errno; 84 | } 85 | Isolate* isolate = info.GetIsolate(); 86 | Local res = Array::New(isolate, 3); 87 | res->Set(0, Integer::New(isolate, r)); 88 | res->Set(1, Integer::New(isolate, 0)); 89 | res->Set(2, Integer::New(isolate, err)); 90 | info.GetReturnValue().Set(res); 91 | } 92 | 93 | void init(Handle target) { 94 | NODE_SET_METHOD(target, "Syscall", Syscall); 95 | NODE_SET_METHOD(target, "Syscall6", Syscall6); 96 | } 97 | 98 | NODE_MODULE(syscall, init); 99 | -------------------------------------------------------------------------------- /nosync/map.go: -------------------------------------------------------------------------------- 1 | package nosync 2 | 3 | // Map is a concurrent map with amortized-constant-time loads, stores, and deletes. 4 | // It is safe for multiple goroutines to call a Map's methods concurrently. 5 | // 6 | // The zero Map is valid and empty. 7 | // 8 | // A Map must not be copied after first use. 9 | type Map struct { 10 | m map[interface{}]interface{} 11 | } 12 | 13 | // Load returns the value stored in the map for a key, or nil if no 14 | // value is present. 15 | // The ok result indicates whether value was found in the map. 16 | func (m *Map) Load(key interface{}) (value interface{}, ok bool) { 17 | value, ok = m.m[key] 18 | return value, ok 19 | } 20 | 21 | // Store sets the value for a key. 22 | func (m *Map) Store(key, value interface{}) { 23 | if m.m == nil { 24 | m.m = make(map[interface{}]interface{}) 25 | } 26 | m.m[key] = value 27 | } 28 | 29 | // LoadOrStore returns the existing value for the key if present. 30 | // Otherwise, it stores and returns the given value. 31 | // The loaded result is true if the value was loaded, false if stored. 32 | func (m *Map) LoadOrStore(key, value interface{}) (actual interface{}, loaded bool) { 33 | if value, ok := m.m[key]; ok { 34 | return value, true 35 | } 36 | if m.m == nil { 37 | m.m = make(map[interface{}]interface{}) 38 | } 39 | m.m[key] = value 40 | return value, false 41 | } 42 | 43 | // Delete deletes the value for a key. 44 | func (m *Map) Delete(key interface{}) { 45 | if m.m == nil { 46 | return 47 | } 48 | delete(m.m, key) 49 | } 50 | 51 | // Range calls f sequentially for each key and value present in the map. 52 | // If f returns false, range stops the iteration. 53 | // 54 | // Range does not necessarily correspond to any consistent snapshot of the Map's 55 | // contents: no key will be visited more than once, but if the value for any key 56 | // is stored or deleted concurrently, Range may reflect any mapping for that key 57 | // from any point during the Range call. 58 | // 59 | // Range may be O(N) with the number of elements in the map even if f returns 60 | // false after a constant number of calls. 61 | func (m *Map) Range(f func(key, value interface{}) bool) { 62 | for k, v := range m.m { 63 | if !f(k, v) { 64 | break 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /nosync/mutex.go: -------------------------------------------------------------------------------- 1 | package nosync 2 | 3 | // Mutex is a dummy which is non-blocking. 4 | type Mutex struct { 5 | locked bool 6 | } 7 | 8 | // Lock locks m. It is a run-time error if m is already locked. 9 | func (m *Mutex) Lock() { 10 | if m.locked { 11 | panic("nosync: mutex is already locked") 12 | } 13 | m.locked = true 14 | } 15 | 16 | // Unlock unlocks m. It is a run-time error if m is not locked. 17 | func (m *Mutex) Unlock() { 18 | if !m.locked { 19 | panic("nosync: unlock of unlocked mutex") 20 | } 21 | m.locked = false 22 | } 23 | 24 | // RWMutex is a dummy which is non-blocking. 25 | type RWMutex struct { 26 | writeLocked bool 27 | readLockCounter int 28 | } 29 | 30 | // Lock locks m for writing. It is a run-time error if rw is already locked for reading or writing. 31 | func (rw *RWMutex) Lock() { 32 | if rw.readLockCounter != 0 || rw.writeLocked { 33 | panic("nosync: mutex is already locked") 34 | } 35 | rw.writeLocked = true 36 | } 37 | 38 | // Unlock unlocks rw for writing. It is a run-time error if rw is not locked for writing. 39 | func (rw *RWMutex) Unlock() { 40 | if !rw.writeLocked { 41 | panic("nosync: unlock of unlocked mutex") 42 | } 43 | rw.writeLocked = false 44 | } 45 | 46 | // RLock locks m for reading. It is a run-time error if rw is already locked for reading or writing. 47 | func (rw *RWMutex) RLock() { 48 | if rw.writeLocked { 49 | panic("nosync: mutex is already locked") 50 | } 51 | rw.readLockCounter++ 52 | } 53 | 54 | // RUnlock undoes a single RLock call; it does not affect other simultaneous readers. It is a run-time error if rw is not locked for reading. 55 | func (rw *RWMutex) RUnlock() { 56 | if rw.readLockCounter == 0 { 57 | panic("nosync: unlock of unlocked mutex") 58 | } 59 | rw.readLockCounter-- 60 | } 61 | 62 | // WaitGroup is a dummy which is non-blocking. 63 | type WaitGroup struct { 64 | counter int 65 | } 66 | 67 | // Add adds delta, which may be negative, to the WaitGroup If the counter goes negative, Add panics. 68 | func (wg *WaitGroup) Add(delta int) { 69 | wg.counter += delta 70 | if wg.counter < 0 { 71 | panic("sync: negative WaitGroup counter") 72 | } 73 | } 74 | 75 | // Done decrements the WaitGroup counter. 76 | func (wg *WaitGroup) Done() { 77 | wg.Add(-1) 78 | } 79 | 80 | // Wait panics if the WaitGroup counter is not zero. 81 | func (wg *WaitGroup) Wait() { 82 | if wg.counter != 0 { 83 | panic("sync: WaitGroup counter not zero") 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /nosync/once.go: -------------------------------------------------------------------------------- 1 | package nosync 2 | 3 | // Once is an object that will perform exactly one action. 4 | type Once struct { 5 | doing bool 6 | done bool 7 | } 8 | 9 | // Do calls the function f if and only if Do is being called for the 10 | // first time for this instance of Once. In other words, given 11 | // var once Once 12 | // if once.Do(f) is called multiple times, only the first call will invoke f, 13 | // even if f has a different value in each invocation. A new instance of 14 | // Once is required for each function to execute. 15 | // 16 | // Do is intended for initialization that must be run exactly once. Since f 17 | // is niladic, it may be necessary to use a function literal to capture the 18 | // arguments to a function to be invoked by Do: 19 | // config.once.Do(func() { config.init(filename) }) 20 | // 21 | // If f causes Do to be called, it will panic. 22 | // 23 | // If f panics, Do considers it to have returned; future calls of Do return 24 | // without calling f. 25 | // 26 | func (o *Once) Do(f func()) { 27 | if o.done { 28 | return 29 | } 30 | if o.doing { 31 | panic("nosync: Do called within f") 32 | } 33 | o.doing = true 34 | defer func() { 35 | o.doing = false 36 | o.done = true 37 | }() 38 | f() 39 | } 40 | -------------------------------------------------------------------------------- /nosync/pool.go: -------------------------------------------------------------------------------- 1 | package nosync 2 | 3 | // A Pool is a set of temporary objects that may be individually saved and 4 | // retrieved. 5 | // 6 | // Any item stored in the Pool may be removed automatically at any time without 7 | // notification. If the Pool holds the only reference when this happens, the 8 | // item might be deallocated. 9 | // 10 | // A Pool is safe for use by multiple goroutines simultaneously. 11 | // 12 | // Pool's purpose is to cache allocated but unused items for later reuse, 13 | // relieving pressure on the garbage collector. That is, it makes it easy to 14 | // build efficient, thread-safe free lists. However, it is not suitable for all 15 | // free lists. 16 | // 17 | // An appropriate use of a Pool is to manage a group of temporary items 18 | // silently shared among and potentially reused by concurrent independent 19 | // clients of a package. Pool provides a way to amortize allocation overhead 20 | // across many clients. 21 | // 22 | // An example of good use of a Pool is in the fmt package, which maintains a 23 | // dynamically-sized store of temporary output buffers. The store scales under 24 | // load (when many goroutines are actively printing) and shrinks when 25 | // quiescent. 26 | // 27 | // On the other hand, a free list maintained as part of a short-lived object is 28 | // not a suitable use for a Pool, since the overhead does not amortize well in 29 | // that scenario. It is more efficient to have such objects implement their own 30 | // free list. 31 | // 32 | type Pool struct { 33 | store []interface{} 34 | New func() interface{} 35 | } 36 | 37 | // Get selects an arbitrary item from the Pool, removes it from the 38 | // Pool, and returns it to the caller. 39 | // Get may choose to ignore the pool and treat it as empty. 40 | // Callers should not assume any relation between values passed to Put and 41 | // the values returned by Get. 42 | // 43 | // If Get would otherwise return nil and p.New is non-nil, Get returns 44 | // the result of calling p.New. 45 | func (p *Pool) Get() interface{} { 46 | if len(p.store) == 0 { 47 | if p.New != nil { 48 | return p.New() 49 | } 50 | return nil 51 | } 52 | x := p.store[len(p.store)-1] 53 | p.store = p.store[:len(p.store)-1] 54 | return x 55 | } 56 | 57 | // Put adds x to the pool. 58 | func (p *Pool) Put(x interface{}) { 59 | if x == nil { 60 | return 61 | } 62 | p.store = append(p.store, x) 63 | } 64 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gopherjs", 3 | "requires": true, 4 | "lockfileVersion": 1, 5 | "dependencies": { 6 | "commander": { 7 | "version": "2.13.0", 8 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", 9 | "integrity": "sha1-aWS8pnaF33wfFDDFhPB9dZeIW5w=", 10 | "dev": true 11 | }, 12 | "prettier": { 13 | "version": "1.12.0", 14 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.12.0.tgz", 15 | "integrity": "sha512-Wz0SMncgaglBzDcohH3ZIAi4nVpzOIEweFzCOmgVEoRSeO72b4dcKGfgxoRGVMaFlh1r7dlVaJ+f3CIHfeH6xg==", 16 | "dev": true 17 | }, 18 | "source-map": { 19 | "version": "0.6.1", 20 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 21 | "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", 22 | "dev": true 23 | }, 24 | "uglify-es": { 25 | "version": "3.3.9", 26 | "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz", 27 | "integrity": "sha1-DBxPBwC+2NvBJM2zBNJZLKID5nc=", 28 | "dev": true, 29 | "requires": { 30 | "commander": "~2.13.0", 31 | "source-map": "~0.6.1" 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gopherjs", 3 | "devDependencies": { 4 | "uglify-es": "3.3.9", 5 | "prettier": "1.12.0" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /testdata/build.txt: -------------------------------------------------------------------------------- 1 | # Tests for gopherjs build command in module mode. These tests are 2 | # largely copied from their GOPATH equivalents. Includes checks 3 | # for behaviour, staleness and output side effects (e.g. files in 4 | # $GOPATH/pkg) 5 | # 6 | # A change from the original GopherJS here, we do _not_ now install 7 | # a dependency in $GOPATH/pkg unless explicitly asked to do so by 8 | # gopherjs install. 9 | 10 | env HOME=$WORK/home 11 | mkdir $HOME 12 | env GOPATH=$WORK/go 13 | cd hello 14 | go mod edit -require=github.com/gopherjs/gopherjs@v0.0.0 -replace=github.com/gopherjs/gopherjs=$SELF 15 | 16 | cp blah/blah.go.fish blah/blah.go 17 | 18 | # Ensure that we get the "same" output from a file arg or an implicit 19 | # or explicit package argument. We don't have a neat way (yet) of 20 | # comparing the main.js output with the package output, allowing for the 21 | # difference in pkg name 22 | ! exists hello.js 23 | gopherjs build 24 | exists hello.js 25 | exec node hello.js 26 | stdout '^Today we will eat fish$' 27 | ! stderr .+ 28 | cp hello.js implicit.js 29 | rm hello.js 30 | ! exists hello.js 31 | gopherjs build example.com/hello 32 | exists hello.js 33 | exec node hello.js 34 | stdout '^Today we will eat fish$' 35 | ! stderr .+ 36 | cp hello.js explicit.js 37 | rm hello.js 38 | cmp implicit.js explicit.js 39 | ! exists hello.js main.js 40 | gopherjs build main.go 41 | exists main.js 42 | exec node main.js 43 | stdout '^Today we will eat fish$' 44 | ! stderr .+ 45 | ! exists $GOPATH/pkg/${GOOS}_js 46 | 47 | # tidy up 48 | rm hello.js.map implicit.js explicit.js main.js main.js.map 49 | 50 | # non-command package 51 | cd blah 52 | gopherjs build 53 | ! exists $GOPATH/pkg/${GOOS}_js 54 | ! exists blah.js 55 | 56 | cd .. 57 | 58 | # Staleness checks 59 | cp blah/blah.go.fish blah/blah.go 60 | ! exists hello.js hello.js.map 61 | gopherjs build 62 | ! stdout .+ 63 | ! stderr .+ 64 | exists hello.js hello.js.map 65 | ! modified hello.js 66 | ! changed hello.js 67 | exec node hello.js 68 | stdout '^Today we will eat fish$' 69 | ! stderr .+ 70 | gopherjs build 71 | modified hello.js 72 | ! changed hello.js 73 | cp blah/blah.go.chips blah/blah.go 74 | gopherjs build 75 | modified hello.js 76 | changed hello.js 77 | exec node hello.js 78 | stdout '^Today we will eat chips$' 79 | ! stderr .+ 80 | gopherjs build --tags thin 81 | modified hello.js 82 | changed hello.js 83 | exec node hello.js 84 | stdout '^Today we will eat thin chips$' 85 | ! stderr .+ 86 | 87 | -- hello/go.mod -- 88 | module example.com/hello 89 | 90 | -- hello/main.go -- 91 | package main 92 | 93 | import "example.com/hello/blah" 94 | 95 | func main() { 96 | print("Today we will eat", blah.Name) 97 | } 98 | 99 | -- hello/main_test.go.fish -- 100 | package main 101 | 102 | import "fmt" 103 | import "testing" 104 | import "example.com/hello/blah" 105 | 106 | 107 | func TestBlah(t *testing.T) { 108 | fmt.Println(blah.Name) 109 | if exp := "fish"; blah.Name != exp { 110 | t.Fatalf("expected %v; got %v", exp, blah.Name) 111 | } 112 | } 113 | 114 | -- hello/main_test.go.chips -- 115 | // +build !thin 116 | 117 | package main 118 | 119 | import "fmt" 120 | import "testing" 121 | import "example.com/hello/blah" 122 | 123 | 124 | func TestBlah(t *testing.T) { 125 | fmt.Println(blah.Name) 126 | if exp := "chips"; blah.Name != exp { 127 | t.Fatalf("expected %v; got %v", exp, blah.Name) 128 | } 129 | } 130 | 131 | -- hello/blah/blah.go.fish -- 132 | package blah 133 | 134 | const Name = "fish" 135 | 136 | -- hello/blah/blah.go.chips -- 137 | // +build !thin 138 | 139 | package blah 140 | const Name = "chips" 141 | 142 | -- hello/blah/blahthin.go -- 143 | // +build thin 144 | 145 | package blah 146 | const Name = "thin chips" 147 | 148 | -------------------------------------------------------------------------------- /testdata/build_gopath.txt: -------------------------------------------------------------------------------- 1 | # Tests for gopherjs build command in GOPATH mode. Includes checks for 2 | # behaviour, staleness and output side effects (e.g. files in $GOPATH/pkg) 3 | # 4 | # A change from the original GopherJS here, we do _not_ now install 5 | # a dependency in $GOPATH/pkg unless explicitly asked to do so by 6 | # gopherjs install. 7 | 8 | env HOME=$WORK/home 9 | mkdir $HOME 10 | env GOPATH=$WORK/go 11 | 12 | cd go/src/example.com/hello 13 | 14 | cp blah/blah.go.fish blah/blah.go 15 | 16 | # Ensure that we get the "same" output from a file arg or an implicit 17 | # or explicit package argument. We don't have a neat way (yet) of 18 | # comparing the main.js output with the package output, allowing for the 19 | # difference in pkg name 20 | ! exists hello.js 21 | gopherjs build 22 | exists hello.js 23 | exec node hello.js 24 | stdout '^Today we will eat fish$' 25 | ! stderr .+ 26 | cp hello.js implicit.js 27 | rm hello.js 28 | ! exists hello.js 29 | gopherjs build example.com/hello 30 | exists hello.js 31 | exec node hello.js 32 | stdout '^Today we will eat fish$' 33 | ! stderr .+ 34 | cp hello.js explicit.js 35 | rm hello.js 36 | cmp implicit.js explicit.js 37 | ! exists hello.js main.js 38 | gopherjs build main.go 39 | exists main.js 40 | exec node main.js 41 | stdout '^Today we will eat fish$' 42 | ! stderr .+ 43 | ! exists $GOPATH/pkg 44 | 45 | # tidy up 46 | rm hello.js.map implicit.js explicit.js main.js main.js.map 47 | 48 | # non-command package 49 | cd blah 50 | gopherjs build 51 | ! exists $GOPATH/pkg 52 | ! exists blah.js 53 | 54 | cd .. 55 | 56 | # Staleness checks 57 | cp blah/blah.go.fish blah/blah.go 58 | ! exists hello.js hello.js.map 59 | gopherjs build 60 | ! stdout .+ 61 | ! stderr .+ 62 | exists hello.js hello.js.map 63 | ! modified hello.js 64 | ! changed hello.js 65 | exec node hello.js 66 | stdout '^Today we will eat fish$' 67 | ! stderr .+ 68 | gopherjs build 69 | modified hello.js 70 | ! changed hello.js 71 | cp blah/blah.go.chips blah/blah.go 72 | gopherjs build 73 | modified hello.js 74 | changed hello.js 75 | exec node hello.js 76 | stdout '^Today we will eat chips$' 77 | ! stderr .+ 78 | gopherjs build --tags thin 79 | modified hello.js 80 | changed hello.js 81 | exec node hello.js 82 | stdout '^Today we will eat thin chips$' 83 | ! stderr .+ 84 | 85 | -- go/src/example.com/hello/main.go -- 86 | package main 87 | 88 | import "example.com/hello/blah" 89 | 90 | func main() { 91 | print("Today we will eat", blah.Name) 92 | } 93 | 94 | -- go/src/example.com/hello/main_test.go.fish -- 95 | package main 96 | 97 | import "fmt" 98 | import "testing" 99 | import "example.com/hello/blah" 100 | 101 | 102 | func TestBlah(t *testing.T) { 103 | fmt.Println(blah.Name) 104 | if exp := "fish"; blah.Name != exp { 105 | t.Fatalf("expected %v; got %v", exp, blah.Name) 106 | } 107 | } 108 | 109 | -- go/src/example.com/hello/main_test.go.chips -- 110 | // +build !thin 111 | 112 | package main 113 | 114 | import "fmt" 115 | import "testing" 116 | import "example.com/hello/blah" 117 | 118 | 119 | func TestBlah(t *testing.T) { 120 | fmt.Println(blah.Name) 121 | if exp := "chips"; blah.Name != exp { 122 | t.Fatalf("expected %v; got %v", exp, blah.Name) 123 | } 124 | } 125 | 126 | -- go/src/example.com/hello/blah/blah.go.fish -- 127 | package blah 128 | 129 | const Name = "fish" 130 | 131 | -- go/src/example.com/hello/blah/blah.go.chips -- 132 | // +build !thin 133 | 134 | package blah 135 | const Name = "chips" 136 | 137 | -- go/src/example.com/hello/blah/blahthin.go -- 138 | // +build thin 139 | 140 | package blah 141 | const Name = "thin chips" 142 | 143 | -------------------------------------------------------------------------------- /testdata/compile_error.txt: -------------------------------------------------------------------------------- 1 | # Verify the stderr output in case of compiler-issues 2 | 3 | env HOME=$WORK/home 4 | mkdir $HOME 5 | env GOPATH=$WORK/go 6 | go mod edit -require=github.com/gopherjs/gopherjs@v0.0.0 -replace=github.com/gopherjs/gopherjs=$SELF 7 | 8 | # run 9 | ! gopherjs run main.go 10 | ! stdout .+ 11 | cmp stderr stderr.golden 12 | 13 | # build 14 | ! gopherjs build main.go 15 | ! stdout .+ 16 | cmp stderr stderr.golden 17 | 18 | # install 19 | ! gopherjs install 20 | ! stdout .+ 21 | cmp stderr stderr.golden 22 | 23 | # test 24 | ! gopherjs test 25 | ! stdout .+ 26 | cmp stderr stderr.golden 27 | 28 | -- go.mod -- 29 | module mod.com 30 | 31 | -- main.go -- 32 | package main 33 | 34 | func() main { 35 | -- main_test.go -- 36 | package main 37 | -- stderr.golden -- 38 | main.go:3:13: expected '(', found '{' 39 | -------------------------------------------------------------------------------- /testdata/compiler_unused_nil_assign.txt: -------------------------------------------------------------------------------- 1 | env HOME=$WORK/home 2 | mkdir $HOME 3 | env GOPATH=$WORK/go 4 | go mod edit -require=github.com/gopherjs/gopherjs@v0.0.0 -replace=github.com/gopherjs/gopherjs=$SELF 5 | 6 | gopherjs run . 7 | stdout '^hello, world!$' 8 | 9 | -- go.mod -- 10 | module mod 11 | 12 | -- nilref.go -- 13 | package main 14 | 15 | func main() { 16 | var _ interface{} = nil 17 | print("hello, world!") 18 | } 19 | 20 | -------------------------------------------------------------------------------- /testdata/help.txt: -------------------------------------------------------------------------------- 1 | gopherjs --help 2 | stdout '^GopherJS is a tool for compiling Go source code to JavaScript.$' 3 | ! stderr .+ 4 | -------------------------------------------------------------------------------- /testdata/install.txt: -------------------------------------------------------------------------------- 1 | # Tests for gopherjs install command in GOPATH mode. These tests 2 | # are largely copied from their GOPATH equivalents. Includes checks 3 | # for behaviour, staleness and output side effects (e.g. files in 4 | # $GOPATH/pkg) 5 | # 6 | # A change from the original GopherJS here, we do _not_ now install 7 | # a dependency in $GOPATH/pkg unless explicitly asked to do so by 8 | # gopherjs install. 9 | 10 | env HOME=$WORK/home 11 | mkdir $HOME 12 | env GOPATH=$WORK/go 13 | cd hello 14 | go mod edit -require=github.com/gopherjs/gopherjs@v0.0.0 -replace=github.com/gopherjs/gopherjs=$SELF 15 | 16 | cp blah/blah.go.fish blah/blah.go 17 | 18 | # Ensure that we get the "same" output from a file arg or an implicit 19 | # or explicit package argument. We don't have a neat way (yet) of 20 | # comparing the main.js output with the package output, allowing for the 21 | # difference in pkg name 22 | ! exists $GOPATH/pkg/${GOOS}_js $GOPATH/bin 23 | gopherjs install 24 | ! exists $GOPATH/pkg/${GOOS}_js 25 | exists $GOPATH/bin/hello.js 26 | ! modified $GOPATH/bin/hello.js 27 | ! changed $GOPATH/bin/hello.js 28 | exec node $GOPATH/bin/hello.js 29 | stdout '^Today we will eat fish$' 30 | ! stderr .+ 31 | gopherjs install example.com/hello 32 | ! exists $GOPATH/pkg/${GOOS}_js 33 | modified $GOPATH/bin/hello.js 34 | ! changed $GOPATH/bin/hello.js 35 | 36 | rm $GOPATH/pkg $GOPATH/bin 37 | 38 | # non-command package 39 | ! exists $GOPATH/pkg/${GOOS}_js $GOPATH/bin 40 | cd blah 41 | gopherjs install 42 | ! exists $GOPATH/bin 43 | exists $GOPATH/pkg/${GOOS}_js/example.com/hello/blah.a 44 | ! modified $GOPATH/pkg/linux_js/example.com/hello/blah.a 45 | ! changed $GOPATH/pkg/linux_js/example.com/hello/blah.a 46 | gopherjs install example.com/hello 47 | modified $GOPATH/pkg/linux_js/example.com/hello/blah.a 48 | ! changed $GOPATH/pkg/linux_js/example.com/hello/blah.a 49 | 50 | cd .. 51 | rm $GOPATH/pkg $GOPATH/bin 52 | 53 | modified -clear $GOPATH/pkg/linux_js/example.com/hello/blah.a 54 | modified -clear $GOPATH/bin/hello.js 55 | changed -clear $GOPATH/pkg/linux_js/example.com/hello/blah.a 56 | changed -clear $GOPATH/bin/hello.js 57 | 58 | # Staleness checks 59 | ! exists $GOPATH/pkg/${GOOS}_js $GOPATH/bin 60 | cp blah/blah.go.fish blah/blah.go 61 | gopherjs install 62 | ! stdout .+ 63 | ! stderr .+ 64 | exists $GOPATH/bin/hello.js 65 | ! modified $GOPATH/bin/hello.js 66 | ! changed $GOPATH/bin/hello.js 67 | exec node $GOPATH/bin/hello.js 68 | stdout '^Today we will eat fish$' 69 | ! stderr .+ 70 | gopherjs install 71 | modified $GOPATH/bin/hello.js 72 | ! changed $GOPATH/bin/hello.js 73 | cp blah/blah.go.chips blah/blah.go 74 | gopherjs install 75 | modified $GOPATH/bin/hello.js 76 | changed $GOPATH/bin/hello.js 77 | exec node $GOPATH/bin/hello.js 78 | stdout '^Today we will eat chips$' 79 | ! stderr .+ 80 | gopherjs install --tags thin 81 | modified $GOPATH/bin/hello.js 82 | changed $GOPATH/bin/hello.js 83 | exec node $GOPATH/bin/hello.js 84 | stdout '^Today we will eat thin chips$' 85 | ! stderr .+ 86 | 87 | -- hello/go.mod -- 88 | module example.com/hello 89 | 90 | -- hello/main.go -- 91 | package main 92 | 93 | import "example.com/hello/blah" 94 | 95 | func main() { 96 | print("Today we will eat", blah.Name) 97 | } 98 | 99 | -- hello/main_test.go.fish -- 100 | package main 101 | 102 | import "fmt" 103 | import "testing" 104 | import "example.com/hello/blah" 105 | 106 | 107 | func TestBlah(t *testing.T) { 108 | fmt.Println(blah.Name) 109 | if exp := "fish"; blah.Name != exp { 110 | t.Fatalf("expected %v; got %v", exp, blah.Name) 111 | } 112 | } 113 | 114 | -- hello/main_test.go.chips -- 115 | // +build !thin 116 | 117 | package main 118 | 119 | import "fmt" 120 | import "testing" 121 | import "example.com/hello/blah" 122 | 123 | 124 | func TestBlah(t *testing.T) { 125 | fmt.Println(blah.Name) 126 | if exp := "chips"; blah.Name != exp { 127 | t.Fatalf("expected %v; got %v", exp, blah.Name) 128 | } 129 | } 130 | 131 | -- hello/blah/blah.go.fish -- 132 | package blah 133 | 134 | const Name = "fish" 135 | 136 | -- hello/blah/blah.go.chips -- 137 | // +build !thin 138 | 139 | package blah 140 | const Name = "chips" 141 | 142 | -- hello/blah/blahthin.go -- 143 | // +build thin 144 | 145 | package blah 146 | const Name = "thin chips" 147 | 148 | -------------------------------------------------------------------------------- /testdata/install_gopath.txt: -------------------------------------------------------------------------------- 1 | # Tests for gopherjs install command in GOPATH mode. Includes checks for 2 | # behaviour, staleness and output side effects (e.g. files in $GOPATH/pkg) 3 | # 4 | # A change from the original GopherJS here, we do _not_ now install 5 | # a dependency in $GOPATH/pkg unless explicitly asked to do so by 6 | # gopherjs install. 7 | 8 | env HOME=$WORK/home 9 | mkdir $HOME 10 | env GOPATH=$WORK/go 11 | 12 | cd go/src/example.com/hello 13 | 14 | cp blah/blah.go.fish blah/blah.go 15 | 16 | # Ensure that we get the "same" output from a file arg or an implicit 17 | # or explicit package argument. We don't have a neat way (yet) of 18 | # comparing the main.js output with the package output, allowing for the 19 | # difference in pkg name 20 | ! exists $GOPATH/pkg $GOPATH/bin 21 | gopherjs install 22 | ! exists $GOPATH/pkg 23 | exists $GOPATH/bin/hello.js 24 | ! modified $GOPATH/bin/hello.js 25 | ! changed $GOPATH/bin/hello.js 26 | exec node $GOPATH/bin/hello.js 27 | stdout '^Today we will eat fish$' 28 | ! stderr .+ 29 | gopherjs install example.com/hello 30 | ! exists $GOPATH/pkg 31 | modified $GOPATH/bin/hello.js 32 | ! changed $GOPATH/bin/hello.js 33 | 34 | rm $GOPATH/pkg $GOPATH/bin 35 | 36 | # non-command package 37 | ! exists $GOPATH/pkg $GOPATH/bin 38 | cd blah 39 | gopherjs install 40 | ! exists $GOPATH/bin 41 | exists $GOPATH/pkg/linux_js/example.com/hello/blah.a 42 | ! modified $GOPATH/pkg/linux_js/example.com/hello/blah.a 43 | ! changed $GOPATH/pkg/linux_js/example.com/hello/blah.a 44 | gopherjs install example.com/hello 45 | modified $GOPATH/pkg/linux_js/example.com/hello/blah.a 46 | ! changed $GOPATH/pkg/linux_js/example.com/hello/blah.a 47 | 48 | cd .. 49 | rm $GOPATH/pkg $GOPATH/bin 50 | 51 | modified -clear $GOPATH/pkg/linux_js/example.com/hello/blah.a 52 | modified -clear $GOPATH/bin/hello.js 53 | changed -clear $GOPATH/pkg/linux_js/example.com/hello/blah.a 54 | changed -clear $GOPATH/bin/hello.js 55 | 56 | # Staleness checks 57 | ! exists $GOPATH/pkg $GOPATH/bin 58 | cp blah/blah.go.fish blah/blah.go 59 | gopherjs install 60 | ! stdout .+ 61 | ! stderr .+ 62 | exists $GOPATH/bin/hello.js 63 | ! modified $GOPATH/bin/hello.js 64 | ! changed $GOPATH/bin/hello.js 65 | exec node $GOPATH/bin/hello.js 66 | stdout '^Today we will eat fish$' 67 | ! stderr .+ 68 | gopherjs install 69 | modified $GOPATH/bin/hello.js 70 | ! changed $GOPATH/bin/hello.js 71 | cp blah/blah.go.chips blah/blah.go 72 | gopherjs install 73 | modified $GOPATH/bin/hello.js 74 | changed $GOPATH/bin/hello.js 75 | exec node $GOPATH/bin/hello.js 76 | stdout '^Today we will eat chips$' 77 | ! stderr .+ 78 | gopherjs install --tags thin 79 | modified $GOPATH/bin/hello.js 80 | changed $GOPATH/bin/hello.js 81 | exec node $GOPATH/bin/hello.js 82 | stdout '^Today we will eat thin chips$' 83 | ! stderr .+ 84 | 85 | -- go/src/example.com/hello/main.go -- 86 | package main 87 | 88 | import "example.com/hello/blah" 89 | 90 | func main() { 91 | print("Today we will eat", blah.Name) 92 | } 93 | 94 | -- go/src/example.com/hello/main_test.go.fish -- 95 | package main 96 | 97 | import "fmt" 98 | import "testing" 99 | import "example.com/hello/blah" 100 | 101 | 102 | func TestBlah(t *testing.T) { 103 | fmt.Println(blah.Name) 104 | if exp := "fish"; blah.Name != exp { 105 | t.Fatalf("expected %v; got %v", exp, blah.Name) 106 | } 107 | } 108 | 109 | -- go/src/example.com/hello/main_test.go.chips -- 110 | // +build !thin 111 | 112 | package main 113 | 114 | import "fmt" 115 | import "testing" 116 | import "example.com/hello/blah" 117 | 118 | 119 | func TestBlah(t *testing.T) { 120 | fmt.Println(blah.Name) 121 | if exp := "chips"; blah.Name != exp { 122 | t.Fatalf("expected %v; got %v", exp, blah.Name) 123 | } 124 | } 125 | 126 | -- go/src/example.com/hello/blah/blah.go.fish -- 127 | package blah 128 | 129 | const Name = "fish" 130 | 131 | -- go/src/example.com/hello/blah/blah.go.chips -- 132 | // +build !thin 133 | 134 | package blah 135 | const Name = "chips" 136 | 137 | -- go/src/example.com/hello/blah/blahthin.go -- 138 | // +build thin 139 | 140 | package blah 141 | const Name = "thin chips" 142 | 143 | -------------------------------------------------------------------------------- /testdata/mod/example.com_hello_v1.0.0.txt: -------------------------------------------------------------------------------- 1 | module example.com/hello@v1.0.0 2 | 3 | -- .mod -- 4 | module "example.com/hello" 5 | 6 | require "example.com/hello" v1.0.0 7 | -- .info -- 8 | {"Version":"v1.0.0","Time":"2018-02-14T15:44:20Z"} 9 | 10 | -- hello.go -- 11 | package hello 12 | 13 | const Greeting = "Hello" 14 | -------------------------------------------------------------------------------- /testdata/mod/github.com_fsnotify_fsnotify_v1.4.7.txt: -------------------------------------------------------------------------------- 1 | module github.com/fsnotify/fsnotify@v1.4.7 2 | 3 | -- .mod -- 4 | module "github.com/fsnotify/fsnotify" 5 | 6 | -- .info -- 7 | {"Version":"v1.4.7","Time":"2018-05-06T08:24:08Z"} 8 | -------------------------------------------------------------------------------- /testdata/mod/github.com_gopherjs_gopherjs_v0.0.0.txt: -------------------------------------------------------------------------------- 1 | module github.com/gopherjs/gopherjs@v0.0.0 2 | 3 | -- .mod -- 4 | module "github.com/gopherjs/gopherjs" 5 | 6 | -- .info -- 7 | {"Version":"v0.0.0","Time":"2018-05-06T08:24:08Z"} 8 | -------------------------------------------------------------------------------- /testdata/mod/github.com_inconshreveable_mousetrap_v1.0.0.txt: -------------------------------------------------------------------------------- 1 | module github.com/inconshreveable/mousetrap@v1.0.0 2 | 3 | -- .mod -- 4 | module "github.com/inconshreveable/mousetrap" 5 | 6 | -- .info -- 7 | {"Version":"v1.0.0","Time":"2018-05-06T08:24:08Z"} 8 | -------------------------------------------------------------------------------- /testdata/mod/github.com_neelance_astrewrite_v0.0.0-20160511093645-99348263ae86.txt: -------------------------------------------------------------------------------- 1 | module github.com/neelance/astrewrite@v0.0.0-20160511093645-99348263ae86 2 | 3 | -- .mod -- 4 | module "github.com/neelance/astrewrite" 5 | 6 | -- .info -- 7 | {"Version":"v0.0.0-20160511093645-99348263ae86","Time":"2018-05-06T08:24:08Z"} 8 | -------------------------------------------------------------------------------- /testdata/mod/github.com_neelance_sourcemap_v0.0.0-20151028013722-8c68805598ab.txt: -------------------------------------------------------------------------------- 1 | module github.com/neelance/sourcemap@v0.0.0-20151028013722-8c68805598ab 2 | 3 | -- .mod -- 4 | module "github.com/neelance/sourcemap" 5 | 6 | -- .info -- 7 | {"Version":"v0.0.0-20151028013722-8c68805598ab","Time":"2018-05-06T08:24:08Z"} 8 | -------------------------------------------------------------------------------- /testdata/mod/github.com_rogpeppe_go-internal_v1.0.1-alpha.1.txt: -------------------------------------------------------------------------------- 1 | module github.com/rogpeppe/go-internal@v1.0.1-alpha.1 2 | 3 | -- .mod -- 4 | module "github.com/rogpeppe/go-internal" 5 | 6 | -- .info -- 7 | {"Version":"v1.0.1-alpha.1","Time":"2018-05-06T08:24:08Z"} 8 | -------------------------------------------------------------------------------- /testdata/mod/github.com_shurcoo!l_go_v0.0.0-20180423040247-9e1955d9fb6e.txt: -------------------------------------------------------------------------------- 1 | module github.com/shurcooL/go@v0.0.0-20180423040247-9e1955d9fb6e 2 | 3 | -- .mod -- 4 | module "github.com/shurcooL/go" 5 | 6 | -- .info -- 7 | {"Version":"v0.0.0-20180423040247-9e1955d9fb6e","Time":"2018-05-06T08:24:08Z"} 8 | -------------------------------------------------------------------------------- /testdata/mod/github.com_shurcoo!l_httpfs_v0.0.0-20181222201310-74dc9339e414.txt: -------------------------------------------------------------------------------- 1 | module github.com/shurcooL/httpfs@v0.0.0-20181222201310-74dc9339e414 2 | 3 | -- .mod -- 4 | module "github.com/shurcooL/httpfs" 5 | 6 | -- .info -- 7 | {"Version":"v0.0.0-20181222201310-74dc9339e414","Time":"2018-05-06T08:24:08Z"} 8 | -------------------------------------------------------------------------------- /testdata/mod/github.com_shurcoo!l_vfsgen_v0.0.0-20180915214035-33ae1944be3f.txt: -------------------------------------------------------------------------------- 1 | module github.com/shurcooL/vfsgen@v0.0.0-20180915214035-33ae1944be3f 2 | 3 | -- .mod -- 4 | module "github.com/shurcooL/vfsgen" 5 | 6 | -- .info -- 7 | {"Version":"v0.0.0-20180915214035-33ae1944be3f","Time":"2018-05-06T08:24:08Z"} 8 | -------------------------------------------------------------------------------- /testdata/mod/github.com_spf13_cobra_v0.0.3.txt: -------------------------------------------------------------------------------- 1 | module github.com/spf13/cobra@v0.0.3 2 | 3 | -- .mod -- 4 | module "github.com/spf13/cobra" 5 | 6 | -- .info -- 7 | {"Version":"v0.0.3","Time":"2018-05-06T08:24:08Z"} 8 | -------------------------------------------------------------------------------- /testdata/mod/github.com_spf13_pflag_v1.0.1.txt: -------------------------------------------------------------------------------- 1 | module github.com/spf13/pflag@v1.0.1 2 | 3 | -- .mod -- 4 | module "github.com/spf13/pflag" 5 | 6 | -- .info -- 7 | {"Version":"v1.0.1","Time":"2018-05-06T08:24:08Z"} 8 | -------------------------------------------------------------------------------- /testdata/mod/golang.org_x_crypto_v0.0.0-20180807104621-f027049dab0a.txt: -------------------------------------------------------------------------------- 1 | module golang.org/x/crypto@v0.0.0-20180807104621-f027049dab0a 2 | 3 | -- .mod -- 4 | module "golang.org/x/crypto" 5 | 6 | -- .info -- 7 | {"Version":"v0.0.0-20180807104621-f027049dab0a","Time":"2018-05-06T08:24:08Z"} 8 | -------------------------------------------------------------------------------- /testdata/mod/golang.org_x_sys_v0.0.0-20180807162357-acbc56fc7007.txt: -------------------------------------------------------------------------------- 1 | module golang.org/x/sys@v0.0.0-20180807162357-acbc56fc7007 2 | 3 | -- .mod -- 4 | module "golang.org/x/sys" 5 | 6 | -- .info -- 7 | {"Version":"v0.0.0-20180807162357-acbc56fc7007","Time":"2018-05-06T08:24:08Z"} 8 | -------------------------------------------------------------------------------- /testdata/mod/golang.org_x_tools_v0.0.0-20190308142131-b40df0fb21c3.txt: -------------------------------------------------------------------------------- 1 | module golang.org/x/tools@v0.0.0-20190308142131-b40df0fb21c3 2 | 3 | -- .mod -- 4 | module "golang.org/x/tools" 5 | 6 | -- .info -- 7 | {"Version":"v0.0.0-20190308142131-b40df0fb21c3","Time":"2018-05-06T08:24:08Z"} 8 | -------------------------------------------------------------------------------- /testdata/modified_changed.txt: -------------------------------------------------------------------------------- 1 | exec touch file 2 | ! modified file 3 | ! changed file 4 | exec touch file 5 | modified file 6 | ! changed file 7 | exec bash -c 'echo string > file' 8 | modified file 9 | changed file 10 | -------------------------------------------------------------------------------- /testdata/run.txt: -------------------------------------------------------------------------------- 1 | # Tests for gopherjs run command in GOPATH mode. These tests are largely 2 | # copied from their GOPATH equivalents. Includes checks for behaviour, 3 | # staleness and output side effects (e.g. files in $GOPATH/pkg) 4 | # 5 | # A change from the original GopherJS here, we do _not_ now install a 6 | # dependency in $GOPATH/pkg unless explicitly asked to do so by gopherjs 7 | # install (i.e. not this command). Also, we allow run to take zero 8 | # argument (implies current directory) or a list of package patterns 9 | # that resolve to a single package. 10 | 11 | env HOME=$WORK/home 12 | mkdir $HOME 13 | env GOPATH=$WORK/go 14 | cd hello 15 | go mod edit -require=github.com/gopherjs/gopherjs@v0.0.0 -replace=github.com/gopherjs/gopherjs=$SELF 16 | 17 | cp blah/blah.go.fish blah/blah.go 18 | 19 | # Ensure that we get the "same" output from a file arg or an implicit 20 | # or explicit package argument. We don't have a neat way (yet) of 21 | # comparing the main.js output with the package output, allowing for the 22 | # difference in pkg name 23 | ! exists exists $GOPATH/pkg/${GOOS}_js $GOPATH/bin 24 | gopherjs run main.go and peas 25 | stdout '^Today we will eat fish and peas$' 26 | ! stderr .+ 27 | ! exists exists $GOPATH/pkg/${GOOS}_js $GOPATH/bin 28 | gopherjs run example.com/hello and peas 29 | stdout '^Today we will eat fish and peas$' 30 | ! stderr .+ 31 | ! exists exists $GOPATH/pkg/${GOOS}_js $GOPATH/bin 32 | gopherjs run . and peas 33 | stdout '^Today we will eat fish and peas$' 34 | ! stderr .+ 35 | ! exists exists $GOPATH/pkg/${GOOS}_js $GOPATH/bin 36 | ! gopherjs run 37 | stderr '^gopherjs run: no go files listed$' 38 | ! gopherjs run ./... and peas 39 | ! stdout .+ 40 | stderr '^gopherjs run: pattern ./... matches multiple packages:$' 41 | ! exists exists $GOPATH/pkg/${GOOS}_js $GOPATH/bin 42 | 43 | # Ensure that gopherjs run does not work for a non-main package. But 44 | # whilst we're there, check that we can still run the main package from 45 | # outside of its directory 46 | cd blah 47 | ! gopherjs run . 48 | ! stdout .+ 49 | stderr '^gopherjs run: example.com/hello/blah is not a main package$' 50 | gopherjs run example.com/hello and peas 51 | stdout '^Today we will eat fish and peas$' 52 | ! stderr .+ 53 | cd .. 54 | ! gopherjs run example.com/hello/blah 55 | ! stdout .+ 56 | stderr '^gopherjs run: example.com/hello/blah is not a main package$' 57 | 58 | # Staleness checks 59 | cp blah/blah.go.chips blah/blah.go 60 | gopherjs run . and peas 61 | stdout '^Today we will eat chips and peas$' 62 | ! stderr .+ 63 | gopherjs run --tags thin . and peas 64 | stdout '^Today we will eat thin chips and peas$' 65 | ! stderr .+ 66 | 67 | -- hello/go.mod -- 68 | module example.com/hello 69 | 70 | -- hello/main.go -- 71 | package main 72 | 73 | import "strings" 74 | import "os" 75 | import "example.com/hello/blah" 76 | 77 | func main() { 78 | print("Today we will eat", blah.Name, strings.Join(os.Args[1:], " ")) 79 | } 80 | 81 | -- hello/main_test.go.fish -- 82 | package main 83 | 84 | import "fmt" 85 | import "testing" 86 | import "example.com/hello/blah" 87 | 88 | 89 | func TestBlah(t *testing.T) { 90 | fmt.Println(blah.Name) 91 | if exp := "fish"; blah.Name != exp { 92 | t.Fatalf("expected %v; got %v", exp, blah.Name) 93 | } 94 | } 95 | 96 | -- hello/main_test.go.chips -- 97 | // +build !thin 98 | 99 | package main 100 | 101 | import "fmt" 102 | import "testing" 103 | import "example.com/hello/blah" 104 | 105 | 106 | func TestBlah(t *testing.T) { 107 | fmt.Println(blah.Name) 108 | if exp := "chips"; blah.Name != exp { 109 | t.Fatalf("expected %v; got %v", exp, blah.Name) 110 | } 111 | } 112 | 113 | -- hello/blah/blah.go.fish -- 114 | package blah 115 | 116 | const Name = "fish" 117 | 118 | -- hello/blah/blah.go.chips -- 119 | // +build !thin 120 | 121 | package blah 122 | const Name = "chips" 123 | 124 | -- hello/blah/blahthin.go -- 125 | // +build thin 126 | 127 | package blah 128 | const Name = "thin chips" 129 | 130 | -------------------------------------------------------------------------------- /testdata/run_gopath.txt: -------------------------------------------------------------------------------- 1 | # Tests for gopherjs run command in GOPATH mode. Includes checks 2 | # for behaviour, staleness and output side effects (e.g. files in 3 | # $GOPATH/pkg) 4 | # 5 | # A change from the original GopherJS here, we do _not_ now install a 6 | # dependency in $GOPATH/pkg unless explicitly asked to do so by gopherjs 7 | # install (i.e. not this command). Also, we allow run to take zero 8 | # argument (implies current directory) or a list of package patterns 9 | # that resolve to a single package. 10 | 11 | env HOME=$WORK/home 12 | mkdir $HOME 13 | env GOPATH=$WORK/go 14 | 15 | cd go/src/example.com/hello 16 | 17 | cp blah/blah.go.fish blah/blah.go 18 | 19 | # Ensure that we get the "same" output from a file arg or an implicit 20 | # or explicit package argument. We don't have a neat way (yet) of 21 | # comparing the main.js output with the package output, allowing for the 22 | # difference in pkg name 23 | ! exists $GOPATH/pkg $GOPATH/bin 24 | gopherjs run main.go and peas 25 | stdout '^Today we will eat fish and peas$' 26 | ! stderr .+ 27 | ! exists $GOPATH/pkg $GOPATH/bin 28 | gopherjs run example.com/hello and peas 29 | stdout '^Today we will eat fish and peas$' 30 | ! stderr .+ 31 | ! exists $GOPATH/pkg $GOPATH/bin 32 | gopherjs run . and peas 33 | stdout '^Today we will eat fish and peas$' 34 | ! stderr .+ 35 | ! exists $GOPATH/pkg $GOPATH/bin 36 | ! gopherjs run 37 | stderr '^gopherjs run: no go files listed$' 38 | ! gopherjs run ./... and peas 39 | ! stdout .+ 40 | stderr '^gopherjs run: pattern ./... matches multiple packages:$' 41 | ! exists $GOPATH/pkg $GOPATH/bin 42 | 43 | # Ensure that gopherjs run does not work for a non-main package. But 44 | # whilst we're there, check that we can still run the main package from 45 | # outside of its directory 46 | cd blah 47 | ! gopherjs run . 48 | ! stdout .+ 49 | stderr '^gopherjs run: example.com/hello/blah is not a main package$' 50 | gopherjs run example.com/hello and peas 51 | stdout '^Today we will eat fish and peas$' 52 | ! stderr .+ 53 | cd .. 54 | ! gopherjs run example.com/hello/blah 55 | ! stdout .+ 56 | stderr '^gopherjs run: example.com/hello/blah is not a main package$' 57 | 58 | # Staleness checks 59 | cp blah/blah.go.chips blah/blah.go 60 | gopherjs run . and peas 61 | stdout '^Today we will eat chips and peas$' 62 | ! stderr .+ 63 | gopherjs run --tags thin . and peas 64 | stdout '^Today we will eat thin chips and peas$' 65 | ! stderr .+ 66 | 67 | -- go/src/example.com/hello/main.go -- 68 | package main 69 | 70 | import "strings" 71 | import "os" 72 | import "example.com/hello/blah" 73 | 74 | func main() { 75 | print("Today we will eat", blah.Name, strings.Join(os.Args[1:], " ")) 76 | } 77 | 78 | -- go/src/example.com/hello/main_test.go.fish -- 79 | package main 80 | 81 | import "fmt" 82 | import "testing" 83 | import "example.com/hello/blah" 84 | 85 | 86 | func TestBlah(t *testing.T) { 87 | fmt.Println(blah.Name) 88 | if exp := "fish"; blah.Name != exp { 89 | t.Fatalf("expected %v; got %v", exp, blah.Name) 90 | } 91 | } 92 | 93 | -- go/src/example.com/hello/main_test.go.chips -- 94 | // +build !thin 95 | 96 | package main 97 | 98 | import "fmt" 99 | import "testing" 100 | import "example.com/hello/blah" 101 | 102 | 103 | func TestBlah(t *testing.T) { 104 | fmt.Println(blah.Name) 105 | if exp := "chips"; blah.Name != exp { 106 | t.Fatalf("expected %v; got %v", exp, blah.Name) 107 | } 108 | } 109 | 110 | -- go/src/example.com/hello/blah/blah.go.fish -- 111 | package blah 112 | 113 | const Name = "fish" 114 | 115 | -- go/src/example.com/hello/blah/blah.go.chips -- 116 | // +build !thin 117 | 118 | package blah 119 | const Name = "chips" 120 | 121 | -- go/src/example.com/hello/blah/blahthin.go -- 122 | // +build thin 123 | 124 | package blah 125 | const Name = "thin chips" 126 | 127 | -------------------------------------------------------------------------------- /testdata/serve.txt: -------------------------------------------------------------------------------- 1 | # Tests for gopherjs serve command in module mode.These tests are 2 | # largely copied from their GOPATH equivalents. Includes checks 3 | # for behaviour, staleness and output side effects (e.g. files in 4 | # $GOPATH/pkg) 5 | # 6 | # A change from the original GopherJS here, we do _not_ now install a 7 | # dependency in $GOPATH/pkg unless explicitly asked to do so by gopherjs 8 | # install (which is not this command). 9 | 10 | env HOME=$WORK/home 11 | mkdir $HOME 12 | env GOPATH=$WORK/go 13 | cd hello 14 | go mod edit -require=github.com/gopherjs/gopherjs@v0.0.0 -replace=github.com/gopherjs/gopherjs=$SELF 15 | 16 | cp blah/blah.go.fish blah/blah.go 17 | 18 | highport GOPHERJSPORT 19 | ! gopherjs serve --http :$GOPHERJSPORT & 20 | sleep 500ms 21 | ! httpget http://:$GOPHERJSPORT/doesnotexist 404.resp 22 | cmp 404.golden 404.resp 23 | # httpget http://:$GOPHERJSPORT/example.com/ list.resp 24 | # cmp list.golden list.resp 25 | httpget http://:$GOPHERJSPORT/example.com/hello/blah blahlist.resp 26 | cmp blahlist.golden blahlist.resp 27 | httpget http://:$GOPHERJSPORT/example.com/hello/ naked.resp 28 | cmp index.html naked.resp 29 | httpget http://:$GOPHERJSPORT/example.com/hello/index.html hello.resp 30 | cmp index.html hello.resp 31 | httpget http://:$GOPHERJSPORT/example.com/hello/cmd/ cmd.resp 32 | cmp cmd/index.golden cmd.resp 33 | gopherjs build 34 | cp hello.js js.golden 35 | rm hello.js 36 | httpget http://:$GOPHERJSPORT/example.com/hello/hello.js js.resp 37 | cmp js.golden js.resp 38 | httpget http://:$GOPHERJSPORT/example.com/hello/hello.js.map js.map.resp 39 | grep '^{"version":3,"file":"hello.js"' js.map.resp 40 | 41 | # Staleness checks 42 | cp blah/blah.go.fish blah/blah.go 43 | gopherjs build 44 | cp hello.js js.golden 45 | rm hello.js 46 | httpget http://:$GOPHERJSPORT/example.com/hello/hello.js js.resp 47 | cmp js.golden js.resp 48 | cp blah/blah.go.chips blah/blah.go 49 | gopherjs build 50 | cp hello.js js.golden 51 | rm hello.js 52 | httpget http://:$GOPHERJSPORT/example.com/hello/hello.js js.resp 53 | cmp js.golden js.resp 54 | 55 | # Use of --tags 56 | highport GOPHERJSPORT 57 | ! gopherjs serve --tags thin --http :$GOPHERJSPORT & 58 | sleep 500ms 59 | gopherjs build --tags thin 60 | cp hello.js js.golden 61 | rm hello.js 62 | httpget http://:$GOPHERJSPORT/example.com/hello/hello.js js.resp 63 | cmp js.golden js.resp 64 | 65 | stop 66 | 67 | -- hello/go.mod -- 68 | module example.com/hello 69 | 70 | -- hello/index.html -- 71 | Our index 72 | -- hello/cmd/main.go -- 73 | package main 74 | 75 | func main() {} 76 | -- hello/main.go -- 77 | package main 78 | 79 | import "example.com/hello/blah" 80 | 81 | func main() { 82 | print("Today we will eat", blah.Name) 83 | } 84 | 85 | -- hello/main_test.go.fish -- 86 | package main 87 | 88 | import "fmt" 89 | import "testing" 90 | import "example.com/hello/blah" 91 | 92 | 93 | func TestBlah(t *testing.T) { 94 | fmt.Println(blah.Name) 95 | if exp := "fish"; blah.Name != exp { 96 | t.Fatalf("expected %v; got %v", exp, blah.Name) 97 | } 98 | } 99 | 100 | -- hello/main_test.go.chips -- 101 | // +build !thin 102 | 103 | package main 104 | 105 | import "fmt" 106 | import "testing" 107 | import "example.com/hello/blah" 108 | 109 | 110 | func TestBlah(t *testing.T) { 111 | fmt.Println(blah.Name) 112 | if exp := "chips"; blah.Name != exp { 113 | t.Fatalf("expected %v; got %v", exp, blah.Name) 114 | } 115 | } 116 | 117 | -- hello/blah/blah.go.fish -- 118 | package blah 119 | 120 | const Name = "fish" 121 | 122 | -- hello/blah/blah.go.chips -- 123 | // +build !thin 124 | 125 | package blah 126 | const Name = "chips" 127 | 128 | -- hello/blah/blahthin.go -- 129 | // +build thin 130 | 131 | package blah 132 | const Name = "thin chips" 133 | 134 | -- hello/list.golden -- 135 |
136 | hello/
137 | 
138 | -- hello/404.golden -- 139 | 404 page not found 140 | -- hello/blahlist.golden -- 141 |
142 | blah.go
143 | blah.go.chips
144 | blah.go.fish
145 | blahthin.go
146 | 
147 | -- hello/cmd/index.golden -- 148 | 149 | -------------------------------------------------------------------------------- /testdata/serve_gopath.txt: -------------------------------------------------------------------------------- 1 | # Tests for gopherjs serve command in GOPATH mode. Includes checks for 2 | # behaviour, staleness and output side effects (e.g. files in $GOPATH/pkg) 3 | # 4 | # A change from the original GopherJS here, we do _not_ now install 5 | # a dependency in $GOPATH/pkg unless explicitly asked to do so by 6 | # gopherjs install (which is not this command). 7 | 8 | env HOME=$WORK/home 9 | mkdir $HOME 10 | env GOPATH=$WORK/go 11 | 12 | cd go/src/example.com/hello 13 | 14 | cp blah/blah.go.fish blah/blah.go 15 | 16 | highport GOPHERJSPORT 17 | ! gopherjs serve --http :$GOPHERJSPORT & 18 | sleep 500ms 19 | ! httpget http://:$GOPHERJSPORT/doesnotexist 404.resp 20 | cmp 404.golden 404.resp 21 | httpget http://:$GOPHERJSPORT/example.com/ list.resp 22 | cmp list.golden list.resp 23 | httpget http://:$GOPHERJSPORT/example.com/hello/blah/ blahlist.resp 24 | cmp blahlist.golden blahlist.resp 25 | httpget http://:$GOPHERJSPORT/example.com/hello/ naked.resp 26 | cmp index.html naked.resp 27 | httpget http://:$GOPHERJSPORT/example.com/hello/index.html hello.resp 28 | cmp index.html hello.resp 29 | httpget http://:$GOPHERJSPORT/example.com/hello/cmd/ cmd.resp 30 | cmp cmd/index.golden cmd.resp 31 | gopherjs build 32 | cp hello.js js.golden 33 | rm hello.js 34 | httpget http://:$GOPHERJSPORT/example.com/hello/hello.js js.resp 35 | cmp js.golden js.resp 36 | httpget http://:$GOPHERJSPORT/example.com/hello/hello.js.map js.map.resp 37 | grep '^{"version":3,"file":"hello.js"' js.map.resp 38 | 39 | # Staleness checks 40 | cp blah/blah.go.fish blah/blah.go 41 | gopherjs build 42 | cp hello.js js.golden 43 | rm hello.js 44 | httpget http://:$GOPHERJSPORT/example.com/hello/hello.js js.resp 45 | cmp js.golden js.resp 46 | cp blah/blah.go.chips blah/blah.go 47 | gopherjs build 48 | cp hello.js js.golden 49 | rm hello.js 50 | httpget http://:$GOPHERJSPORT/example.com/hello/hello.js js.resp 51 | cmp js.golden js.resp 52 | 53 | # Use of --tags 54 | highport GOPHERJSPORT 55 | ! gopherjs serve --tags thin --http :$GOPHERJSPORT & 56 | sleep 500ms 57 | gopherjs build --tags thin 58 | cp hello.js js.golden 59 | rm hello.js 60 | httpget http://:$GOPHERJSPORT/example.com/hello/hello.js js.resp 61 | cmp js.golden js.resp 62 | 63 | stop 64 | 65 | -- go/src/example.com/hello/index.html -- 66 | Our index 67 | -- go/src/example.com/hello/cmd/main.go -- 68 | package main 69 | 70 | func main() {} 71 | -- go/src/example.com/hello/main.go -- 72 | package main 73 | 74 | import "example.com/hello/blah" 75 | 76 | func main() { 77 | print("Today we will eat", blah.Name) 78 | } 79 | 80 | -- go/src/example.com/hello/main_test.go.fish -- 81 | package main 82 | 83 | import "fmt" 84 | import "testing" 85 | import "example.com/hello/blah" 86 | 87 | 88 | func TestBlah(t *testing.T) { 89 | fmt.Println(blah.Name) 90 | if exp := "fish"; blah.Name != exp { 91 | t.Fatalf("expected %v; got %v", exp, blah.Name) 92 | } 93 | } 94 | 95 | -- go/src/example.com/hello/main_test.go.chips -- 96 | // +build !thin 97 | 98 | package main 99 | 100 | import "fmt" 101 | import "testing" 102 | import "example.com/hello/blah" 103 | 104 | 105 | func TestBlah(t *testing.T) { 106 | fmt.Println(blah.Name) 107 | if exp := "chips"; blah.Name != exp { 108 | t.Fatalf("expected %v; got %v", exp, blah.Name) 109 | } 110 | } 111 | 112 | -- go/src/example.com/hello/blah/blah.go.fish -- 113 | package blah 114 | 115 | const Name = "fish" 116 | 117 | -- go/src/example.com/hello/blah/blah.go.chips -- 118 | // +build !thin 119 | 120 | package blah 121 | const Name = "chips" 122 | 123 | -- go/src/example.com/hello/blah/blahthin.go -- 124 | // +build thin 125 | 126 | package blah 127 | const Name = "thin chips" 128 | 129 | -- go/src/example.com/hello/list.golden -- 130 |
131 | hello/
132 | 
133 | -- go/src/example.com/hello/404.golden -- 134 | 404 page not found 135 | -- go/src/example.com/hello/blahlist.golden -- 136 |
137 | blah.go
138 | blah.go.chips
139 | blah.go.fish
140 | blahthin.go
141 | 
142 | -- go/src/example.com/hello/cmd/index.golden -- 143 | 144 | -------------------------------------------------------------------------------- /testdata/shadow.txt: -------------------------------------------------------------------------------- 1 | # Tests to ensure that in module mode we never take from GOPATH 2 | 3 | env HOME=$WORK/home 4 | env GOPATH=$WORK/gopath 5 | 6 | cd foomood 7 | go mod edit -require=github.com/gopherjs/gopherjs@v0.0.0 -replace=github.com/gopherjs/gopherjs=$SELF 8 | go run . 9 | stdout '^Hello from module foo/bar!$' 10 | gopherjs run main.go 11 | stdout '^Hello from module foo/bar!$' 12 | 13 | -- foomood/go.mod -- 14 | module foo 15 | 16 | -- foomood/main.go -- 17 | package main 18 | 19 | import "foo/bar" 20 | 21 | func main() { 22 | bar.Bar() 23 | } 24 | 25 | -- foomood/bar/bar.go -- 26 | package bar 27 | 28 | import "fmt" 29 | 30 | func Bar() { 31 | fmt.Println("Hello from module foo/bar!") 32 | } 33 | 34 | -- gopath/src/foo/bar/bar.go -- 35 | package bar 36 | 37 | import "fmt" 38 | 39 | func Bar() { 40 | fmt.Println("Hello from GOPATH foo/bar!") 41 | } 42 | -------------------------------------------------------------------------------- /testdata/stdlib_vendor_import.txt: -------------------------------------------------------------------------------- 1 | # Tests to ensure that the special vendors from golang.org/x/* in the 2 | # standard Go distribution work. 3 | 4 | env HOME=$WORK/home 5 | mkdir $HOME 6 | env GOPATH=$WORK/go 7 | 8 | # Check path exists in GOROOT 9 | exists $GOROOT/src/internal/x/crypto/poly1305/poly1305.go 10 | 11 | # GOPATH mode 12 | env GO111MODULE=off 13 | cd go/src/example.com/hello 14 | gopherjs test 15 | 16 | # module mode - disabled pending https://github.com/golang/go/issues/26924 17 | env GO111MODULE=on 18 | cd $WORK 19 | go mod edit -require=github.com/gopherjs/gopherjs@v0.0.0 -replace=github.com/gopherjs/gopherjs=$SELF 20 | exec cat go.mod 21 | gopherjs test 22 | 23 | -- go.mod -- 24 | module mod 25 | 26 | -- main.go -- 27 | package main 28 | 29 | import ( 30 | "fmt" 31 | 32 | // import for transitive dependency on golang_org/x/crypto/cryptobyte 33 | _ "crypto/x509" 34 | ) 35 | 36 | func main() { 37 | fmt.Println("Hello World!") 38 | } 39 | 40 | -- go/src/example.com/hello/main.go -- 41 | package main 42 | 43 | import ( 44 | "fmt" 45 | 46 | // import for transitive dependency on golang_org/x/crypto/cryptobyte 47 | _ "crypto/x509" 48 | ) 49 | 50 | func main() { 51 | fmt.Println("Hello World!") 52 | } 53 | -------------------------------------------------------------------------------- /testdata/test.txt: -------------------------------------------------------------------------------- 1 | # Tests for gopherjs test command in module mode. These tests are 2 | # largely copied from their GOPATH equivalents. Includes checks 3 | # for behaviour, staleness and output side effects (e.g. files in 4 | # $GOPATH/pkg) 5 | # 6 | # A change from the original GopherJS here, we do _not_ now install 7 | # a dependency in $GOPATH/pkg unless explicitly asked to do so by 8 | # gopherjs install (which is not this command). 9 | # 10 | # The use of a build constraint in the test files and imports of 11 | # math/big is to ensure we are correctly computing the module 12 | # dependencies based on the build tags passed to gopherjs. 13 | 14 | env HOME=$WORK/home 15 | mkdir $HOME 16 | env GOPATH=$WORK/go 17 | cd hello 18 | go mod edit -require=github.com/gopherjs/gopherjs@v0.0.0 -replace=github.com/gopherjs/gopherjs=$SELF 19 | 20 | cp blah/blah.go.fish blah/blah.go 21 | 22 | # No test files then test files 23 | ! exists exists $GOPATH/pkg/${GOOS}_js $GOPATH/bin 24 | gopherjs test --tags asdf 25 | stdout '^?\s+example.com/hello\s+\[no test files\]$' 26 | ! stderr .+ 27 | gopherjs test --tags asdf example.com/hello 28 | stdout '^?\s+example.com/hello\s+\[no test files\]$' 29 | ! stderr .+ 30 | cp empty_test.go.empty empty_test.go 31 | cp main_test.go.fish main_test.go 32 | gopherjs test --tags asdf 33 | stdout 'fish' 34 | stdout '^PASS$' 35 | stdout '^ok\s+example.com/hello\s+' 36 | ! stderr .+ 37 | gopherjs test --tags asdf example.com/hello 38 | stdout 'fish' 39 | stdout '^PASS$' 40 | stdout '^ok\s+example.com/hello\s+' 41 | ! stderr .+ 42 | ! exists $GOPATH/pkg/${GOOS}_js $GOPATH/bin 43 | 44 | # mutliple packages 45 | gopherjs test --tags asdf . ./blah 46 | stdout 'fish' 47 | stdout '^PASS$' 48 | stdout '^ok\s+example.com/hello\s+' 49 | stdout '^?\s+example.com/hello/blah\s+\[no test files\]$' 50 | ! stderr .+ 51 | ! exists exists $GOPATH/pkg/${GOOS}_js $GOPATH/bin 52 | 53 | # Staleness checks 54 | ! exists exists $GOPATH/pkg/${GOOS}_js $GOPATH/bin 55 | cp blah/blah.go.fish blah/blah.go 56 | gopherjs test --tags asdf 57 | stdout 'fish' 58 | stdout '^PASS$' 59 | stdout '^ok\s+example.com/hello\s+' 60 | cp blah/blah.go.chips blah/blah.go 61 | ! gopherjs test --tags asdf 62 | stdout '^--- FAIL: TestBlah' 63 | stdout 'expected fish; got chips$' 64 | stdout '^FAIL\s+example.com/hello\s+' 65 | cp main_test.go.chips main_test.go 66 | gopherjs test --tags asdf 67 | stdout 'chips' 68 | stdout '^PASS$' 69 | stdout '^ok\s+example.com/hello\s+' 70 | ! gopherjs test --tags 'thin asdf' 71 | stdout '^--- FAIL: TestBlah' 72 | stdout 'expected chips; got thin chips$' 73 | stdout '^FAIL\s+example.com/hello\s+' 74 | ! stderr .+ 75 | cp main_test.go.thinchips main_test.go 76 | gopherjs test --tags 'asdf thin' 77 | stdout 'thin chips' 78 | stdout '^PASS$' 79 | stdout '^ok\s+example.com/hello\s+' 80 | 81 | -- hello/go.mod -- 82 | module example.com/hello 83 | 84 | -- hello/main.go -- 85 | package main 86 | 87 | import "example.com/hello/blah" 88 | 89 | func main() { 90 | print("Today we will eat", blah.Name) 91 | } 92 | 93 | -- hello/empty_test.go.empty -- 94 | package main 95 | 96 | var x = u 97 | 98 | -- hello/main_test.go.fish -- 99 | // +build asdf 100 | 101 | package main 102 | 103 | import "fmt" 104 | import "testing" 105 | import "example.com/hello/blah" 106 | import "math/big" 107 | 108 | var u big.Word 109 | 110 | func TestBlah(t *testing.T) { 111 | fmt.Println(blah.Name) 112 | if exp := "fish"; blah.Name != exp { 113 | t.Fatalf("expected %v; got %v", exp, blah.Name) 114 | } 115 | } 116 | 117 | -- hello/main_test.go.chips -- 118 | // +build asdf 119 | 120 | package main 121 | 122 | import "fmt" 123 | import "testing" 124 | import "example.com/hello/blah" 125 | import "math/big" 126 | 127 | var u big.Word 128 | 129 | func TestBlah(t *testing.T) { 130 | fmt.Println(blah.Name) 131 | if exp := "chips"; blah.Name != exp { 132 | t.Fatalf("expected %v; got %v", exp, blah.Name) 133 | } 134 | } 135 | 136 | -- hello/main_test.go.thinchips -- 137 | // +build asdf 138 | 139 | package main 140 | 141 | import "fmt" 142 | import "testing" 143 | import "example.com/hello/blah" 144 | import "math/big" 145 | 146 | var u big.Word 147 | 148 | func TestBlah(t *testing.T) { 149 | fmt.Println(blah.Name) 150 | if exp := "thin chips"; blah.Name != exp { 151 | t.Fatalf("expected %v; got %v", exp, blah.Name) 152 | } 153 | } 154 | 155 | -- hello/blah/blah.go.fish -- 156 | package blah 157 | 158 | const Name = "fish" 159 | 160 | -- hello/blah/blah.go.chips -- 161 | // +build !thin 162 | 163 | package blah 164 | const Name = "chips" 165 | 166 | -- hello/blah/blahthin.go -- 167 | // +build thin 168 | 169 | package blah 170 | const Name = "thin chips" 171 | 172 | -------------------------------------------------------------------------------- /testdata/test_gopath.txt: -------------------------------------------------------------------------------- 1 | # Tests for gopherjs test command in GOPATH mode. Includes checks for 2 | # behaviour, staleness and output side effects (e.g. files in $GOPATH/pkg) 3 | # 4 | # A change from the original GopherJS here, we do _not_ now install 5 | # a dependency in $GOPATH/pkg unless explicitly asked to do so by 6 | # gopherjs install (which is not this command). 7 | 8 | env HOME=$WORK/home 9 | mkdir $HOME 10 | env GOPATH=$WORK/go 11 | 12 | cd go/src/example.com/hello 13 | 14 | cp blah/blah.go.fish blah/blah.go 15 | 16 | # No test files then test files 17 | ! exists $GOPATH/pkg $GOPATH/bin 18 | gopherjs test 19 | stdout '^?\s+example.com/hello\s+\[no test files\]$' 20 | ! stderr .+ 21 | gopherjs test example.com/hello 22 | stdout '^?\s+example.com/hello\s+\[no test files\]$' 23 | ! stderr .+ 24 | cp main_test.go.fish main_test.go 25 | gopherjs test 26 | stdout 'fish' 27 | stdout '^PASS$' 28 | stdout '^ok\s+example.com/hello\s+' 29 | ! stderr .+ 30 | gopherjs test example.com/hello 31 | stdout 'fish' 32 | stdout '^PASS$' 33 | stdout '^ok\s+example.com/hello\s+' 34 | ! stderr .+ 35 | ! exists $GOPATH/pkg $GOPATH/bin 36 | 37 | # mutliple packages 38 | gopherjs test . ./blah 39 | stdout 'fish' 40 | stdout '^PASS$' 41 | stdout '^ok\s+example.com/hello\s+' 42 | stdout '^?\s+example.com/hello/blah\s+\[no test files\]$' 43 | ! stderr .+ 44 | ! exists $GOPATH/pkg $GOPATH/bin 45 | 46 | # Staleness checks 47 | ! exists $GOPATH/pkg $GOPATH/bin 48 | cp blah/blah.go.fish blah/blah.go 49 | gopherjs test 50 | stdout 'fish' 51 | stdout '^PASS$' 52 | stdout '^ok\s+example.com/hello\s+' 53 | cp blah/blah.go.chips blah/blah.go 54 | ! gopherjs test 55 | stdout '^--- FAIL: TestBlah' 56 | stdout 'expected fish; got chips$' 57 | stdout '^FAIL\s+example.com/hello\s+' 58 | cp main_test.go.chips main_test.go 59 | gopherjs test 60 | stdout 'chips' 61 | stdout '^PASS$' 62 | stdout '^ok\s+example.com/hello\s+' 63 | ! gopherjs test --tags thin 64 | stdout '^--- FAIL: TestBlah' 65 | stdout 'expected chips; got thin chips$' 66 | stdout '^FAIL\s+example.com/hello\s+' 67 | ! stderr .+ 68 | cp main_test.go.thinchips main_test.go 69 | gopherjs test --tags thin 70 | stdout 'thin chips' 71 | stdout '^PASS$' 72 | stdout '^ok\s+example.com/hello\s+' 73 | 74 | -- go/src/example.com/hello/main.go -- 75 | package main 76 | 77 | import "example.com/hello/blah" 78 | 79 | func main() { 80 | print("Today we will eat", blah.Name) 81 | } 82 | 83 | -- go/src/example.com/hello/main_test.go.fish -- 84 | package main 85 | 86 | import "fmt" 87 | import "testing" 88 | import "example.com/hello/blah" 89 | 90 | 91 | func TestBlah(t *testing.T) { 92 | fmt.Println(blah.Name) 93 | if exp := "fish"; blah.Name != exp { 94 | t.Fatalf("expected %v; got %v", exp, blah.Name) 95 | } 96 | } 97 | 98 | -- go/src/example.com/hello/main_test.go.chips -- 99 | package main 100 | 101 | import "fmt" 102 | import "testing" 103 | import "example.com/hello/blah" 104 | 105 | 106 | func TestBlah(t *testing.T) { 107 | fmt.Println(blah.Name) 108 | if exp := "chips"; blah.Name != exp { 109 | t.Fatalf("expected %v; got %v", exp, blah.Name) 110 | } 111 | } 112 | 113 | -- go/src/example.com/hello/main_test.go.thinchips -- 114 | package main 115 | 116 | import "fmt" 117 | import "testing" 118 | import "example.com/hello/blah" 119 | 120 | 121 | func TestBlah(t *testing.T) { 122 | fmt.Println(blah.Name) 123 | if exp := "thin chips"; blah.Name != exp { 124 | t.Fatalf("expected %v; got %v", exp, blah.Name) 125 | } 126 | } 127 | 128 | -- go/src/example.com/hello/blah/blah.go.fish -- 129 | package blah 130 | 131 | const Name = "fish" 132 | 133 | -- go/src/example.com/hello/blah/blah.go.chips -- 134 | // +build !thin 135 | 136 | package blah 137 | const Name = "chips" 138 | 139 | -- go/src/example.com/hello/blah/blahthin.go -- 140 | // +build thin 141 | 142 | package blah 143 | const Name = "thin chips" 144 | 145 | -------------------------------------------------------------------------------- /testdata/vendor_gopath.txt: -------------------------------------------------------------------------------- 1 | # In GOPATH mode, it should be possible to use GopherJS standalone, that is 2 | # without relying on the source for github.com/gopherjs/gopherjs/... being 3 | # available. The flip is that in module mode we _have_ to have the source. 4 | 5 | env HOME=$WORK/home 6 | mkdir $HOME 7 | env GOPATH=$WORK/go 8 | cd go/src/example.com/hello 9 | 10 | # use the version of github.com/gopherjs/gopherjs/... compiled into the binary 11 | gopherjs run main.go 12 | stdout '^hello using js pkg$' 13 | 14 | # check that we get an error if we choose not to use the compiled in pacakges 15 | ! gopherjs run --tags gopherjsdev main.go 16 | stderr '^cannot find package "github.com/gopherjs/gopherjs/js"' 17 | 18 | # make the source available 19 | cpr $SELF $GOPATH/src/github.com/gopherjs/gopherjs 20 | 21 | # verify we can now actually run with --tags gopherjsdev 22 | gopherjs run --tags gopherjsdev main.go 23 | stdout '^hello using js pkg$' 24 | 25 | -- go/src/example.com/hello/main.go -- 26 | package main 27 | 28 | import "github.com/gopherjs/gopherjs/js" 29 | 30 | func main() { 31 | js.Global.Get("console").Call("log", "hello using js pkg") 32 | } 33 | -------------------------------------------------------------------------------- /testdata/version.txt: -------------------------------------------------------------------------------- 1 | gopherjs version 2 | stdout '^GopherJS [0-9]' 3 | ! stderr .+ 4 | 5 | -------------------------------------------------------------------------------- /tests/alias_test.go: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | type foo struct { 8 | a int 9 | } 10 | 11 | func Test1(t *testing.T) { 12 | calls := 0 13 | bar := func() *foo { 14 | calls++ 15 | return &foo{42} 16 | } 17 | q := &bar().a 18 | if calls != 1 { 19 | t.Error("Should've been a call") 20 | } 21 | *q = 40 22 | if calls != 1 { 23 | t.Error("Wrong number of calls: ", calls, ", should be 1") 24 | } 25 | if *q != 40 { 26 | t.Error("*q != 40") 27 | } 28 | } 29 | 30 | func Test2(t *testing.T) { 31 | f := foo{} 32 | p := &f.a 33 | f = foo{} 34 | f.a = 4 35 | if *p != 4 { 36 | t.Error("*p != 4") 37 | } 38 | } 39 | 40 | func Test3(t *testing.T) { 41 | f := foo{} 42 | p := &f 43 | f = foo{4} 44 | if p.a != 4 { 45 | t.Error("p.a != 4") 46 | } 47 | } 48 | 49 | func Test4(t *testing.T) { 50 | f := struct { 51 | a struct { 52 | b int 53 | } 54 | }{} 55 | p := &f.a 56 | q := &p.b 57 | r := &(*p).b 58 | *r = 4 59 | p = nil 60 | if *r != 4 { 61 | t.Error("*r != 4") 62 | } 63 | if *q != 4 { 64 | t.Error("*q != 4") 65 | } 66 | } 67 | 68 | func Test5(t *testing.T) { 69 | f := struct { 70 | a [3]int 71 | }{[3]int{6, 6, 6}} 72 | s := f.a[:] 73 | f.a = [3]int{4, 4, 4} 74 | if s[1] != 4 { 75 | t.Error("s[1] != 4") 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /tests/compiler_test.go: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestVariadicNil(t *testing.T) { 8 | printVari := func(strs ...string) []string { 9 | return strs 10 | } 11 | 12 | if got := printVari(); got != nil { 13 | t.Errorf("printVari(): got: %#v; want %#v.", got, nil) 14 | } 15 | 16 | { 17 | var want []string 18 | if got := printVari(want...); got != nil { 19 | t.Errorf("printVari(want...): got: %#v; want %#v.", got, nil) 20 | } 21 | } 22 | 23 | { 24 | want := []string{} 25 | if got := printVari(want...); got == nil || len(got) != len(want) { 26 | t.Errorf("printVari(want...): got: %#v; want %#v.", got, want) 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tests/copy_test.go: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | type S struct { 8 | x int 9 | } 10 | 11 | func (a S) test(b S) { 12 | a.x = 0 13 | b.x = 0 14 | } 15 | 16 | type A [1]int 17 | 18 | func (a A) test(b A) { 19 | a[0] = 0 20 | b[0] = 0 21 | } 22 | 23 | func TestCopyOnCall(t *testing.T) { 24 | { 25 | a := S{1} 26 | b := S{2} 27 | 28 | a.test(b) 29 | func() { 30 | defer a.test(b) 31 | }() 32 | 33 | if a.x != 1 { 34 | t.Error("a.x != 1") 35 | } 36 | if b.x != 2 { 37 | t.Error("b.x != 2") 38 | } 39 | } 40 | { 41 | a := A{1} 42 | b := A{2} 43 | 44 | a.test(b) 45 | func() { 46 | defer a.test(b) 47 | }() 48 | 49 | if a[0] != 1 { 50 | t.Error("a[0] != 1") 51 | } 52 | if b[0] != 2 { 53 | t.Error("b[0] != 2") 54 | } 55 | } 56 | } 57 | 58 | func TestSwap(t *testing.T) { 59 | { 60 | a := S{1} 61 | b := S{2} 62 | a, b = b, a 63 | if a.x != 2 || b.x != 1 { 64 | t.Fail() 65 | } 66 | } 67 | { 68 | a := A{1} 69 | b := A{2} 70 | a, b = b, a 71 | if a[0] != 2 || b[0] != 1 { 72 | t.Fail() 73 | } 74 | } 75 | } 76 | 77 | func TestComposite(t *testing.T) { 78 | { 79 | a := S{1} 80 | s := []S{a} 81 | s[0].x = 0 82 | if a.x != 1 { 83 | t.Fail() 84 | } 85 | } 86 | { 87 | a := A{1} 88 | s := []A{a} 89 | s[0][0] = 0 90 | if a[0] != 1 { 91 | t.Fail() 92 | } 93 | } 94 | } 95 | 96 | func TestAppend(t *testing.T) { 97 | { 98 | s := append(make([]S, 3), S{}) // cap(s) == 6 99 | s = s[:6] 100 | if s[5].x != 0 { 101 | t.Fail() 102 | } 103 | } 104 | 105 | { 106 | a := S{1} 107 | b := []S{{2}} 108 | s := append([]S{}, b...) 109 | s[0].x = 0 110 | if a.x != 1 || b[0].x != 2 { 111 | t.Fail() 112 | } 113 | } 114 | } 115 | 116 | type I interface { 117 | M() int 118 | } 119 | 120 | type T S 121 | 122 | func (t T) M() int { 123 | return t.x 124 | } 125 | 126 | func TestExplicitConversion(t *testing.T) { 127 | var coolGuy = S{x: 42} 128 | var i I 129 | i = T(coolGuy) 130 | if i.M() != 42 { 131 | t.Fail() 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /tests/deferblock_test.go: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | ) 7 | 8 | func inner(ch chan struct{}, b bool) ([]byte, error) { 9 | // ensure gopherjs thinks that this inner function can block 10 | if b { 11 | <-ch 12 | } 13 | return []byte{}, nil 14 | } 15 | 16 | // this function's call to inner never blocks, but the deferred 17 | // statement does. 18 | func outer(ch chan struct{}, b bool) ([]byte, error) { 19 | defer func() { 20 | <-ch 21 | }() 22 | 23 | return inner(ch, b) 24 | } 25 | 26 | func TestBlockingInDefer(t *testing.T) { 27 | defer func() { 28 | if x := recover(); x != nil { 29 | t.Errorf("run time panic: %v", x) 30 | } 31 | }() 32 | 33 | ch := make(chan struct{}) 34 | b := false 35 | 36 | go func() { 37 | time.Sleep(5 * time.Millisecond) 38 | ch <- struct{}{} 39 | }() 40 | 41 | outer(ch, b) 42 | } 43 | -------------------------------------------------------------------------------- /tests/doc.go: -------------------------------------------------------------------------------- 1 | // Package tests contains tests for GopherJS. 2 | package tests 3 | -------------------------------------------------------------------------------- /tests/goroutine_test.go: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | "time" 7 | ) 8 | 9 | var expectedI int 10 | 11 | func checkI(t *testing.T, i int) { 12 | if i != expectedI { 13 | t.Errorf("expected %d, got %d", expectedI, i) 14 | } 15 | expectedI++ 16 | } 17 | 18 | func TestDefer(t *testing.T) { 19 | expectedI = 1 20 | defer func() { 21 | checkI(t, 2) 22 | testDefer1(t) 23 | checkI(t, 6) 24 | }() 25 | checkI(t, 1) 26 | } 27 | 28 | func testDefer1(t *testing.T) { 29 | defer func() { 30 | checkI(t, 4) 31 | time.Sleep(0) 32 | checkI(t, 5) 33 | }() 34 | checkI(t, 3) 35 | } 36 | 37 | func TestPanic(t *testing.T) { 38 | expectedI = 1 39 | defer func() { 40 | checkI(t, 8) 41 | err := recover() 42 | time.Sleep(0) 43 | checkI(t, err.(int)) 44 | }() 45 | checkI(t, 1) 46 | testPanic1(t) 47 | checkI(t, -1) 48 | } 49 | 50 | func testPanic1(t *testing.T) { 51 | defer func() { 52 | checkI(t, 6) 53 | time.Sleep(0) 54 | err := recover() 55 | checkI(t, err.(int)) 56 | panic(9) 57 | }() 58 | checkI(t, 2) 59 | testPanic2(t) 60 | checkI(t, -2) 61 | } 62 | 63 | func testPanic2(t *testing.T) { 64 | defer func() { 65 | checkI(t, 5) 66 | }() 67 | checkI(t, 3) 68 | time.Sleep(0) 69 | checkI(t, 4) 70 | panic(7) 71 | checkI(t, -3) 72 | } 73 | 74 | func TestPanicAdvanced(t *testing.T) { 75 | expectedI = 1 76 | defer func() { 77 | recover() 78 | checkI(t, 3) 79 | testPanicAdvanced2(t) 80 | checkI(t, 6) 81 | }() 82 | testPanicAdvanced1(t) 83 | checkI(t, -1) 84 | } 85 | 86 | func testPanicAdvanced1(t *testing.T) { 87 | defer func() { 88 | checkI(t, 2) 89 | }() 90 | checkI(t, 1) 91 | panic("") 92 | } 93 | 94 | func testPanicAdvanced2(t *testing.T) { 95 | defer func() { 96 | checkI(t, 5) 97 | }() 98 | checkI(t, 4) 99 | } 100 | 101 | func TestSelect(t *testing.T) { 102 | expectedI = 1 103 | a := make(chan int) 104 | b := make(chan int) 105 | c := make(chan int) 106 | go func() { 107 | select { 108 | case <-a: 109 | case <-b: 110 | } 111 | }() 112 | go func() { 113 | checkI(t, 1) 114 | a <- 1 115 | select { 116 | case b <- 1: 117 | checkI(t, -1) 118 | default: 119 | checkI(t, 2) 120 | } 121 | c <- 1 122 | }() 123 | <-c 124 | checkI(t, 3) 125 | } 126 | 127 | func TestCloseAfterReceiving(t *testing.T) { 128 | ch := make(chan struct{}) 129 | go func() { 130 | <-ch 131 | close(ch) 132 | }() 133 | ch <- struct{}{} 134 | } 135 | 136 | func TestDeferWithBlocking(t *testing.T) { 137 | ch := make(chan struct{}) 138 | go func() { ch <- struct{}{} }() 139 | defer func() { <-ch }() 140 | fmt.Print("") 141 | return 142 | } 143 | -------------------------------------------------------------------------------- /tests/lowlevel_test.go: -------------------------------------------------------------------------------- 1 | package tests_test 2 | 3 | import ( 4 | "bytes" 5 | "io/ioutil" 6 | "os/exec" 7 | "path/filepath" 8 | "runtime" 9 | "testing" 10 | ) 11 | 12 | // Test for internalization/externalization of time.Time/Date when time package is imported 13 | // but time.Time is unused, causing it to be DCEed (or time package not imported at all). 14 | // 15 | // See https://github.com/gopherjs/gopherjs/issues/279. 16 | func TestTimeInternalizationExternalization(t *testing.T) { 17 | if runtime.GOARCH == "js" { 18 | t.Skip("test meant to be run using normal Go compiler (needs os/exec)") 19 | } 20 | 21 | got, err := exec.Command("gopherjs", "run", filepath.Join("testdata", "time_inexternalization.go")).Output() 22 | if err != nil { 23 | t.Fatalf("%v:\n%s", err, got) 24 | } 25 | 26 | want, err := ioutil.ReadFile(filepath.Join("testdata", "time_inexternalization.out")) 27 | if err != nil { 28 | t.Fatalf("error reading .out file: %v", err) 29 | } 30 | 31 | if !bytes.Equal(got, want) { 32 | t.Fatalf("got != want:\ngot:\n%s\nwant:\n%s", got, want) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/main/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | var mainDidRun = false 4 | 5 | func main() { 6 | mainDidRun = true 7 | } 8 | -------------------------------------------------------------------------------- /tests/main/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "testing" 4 | 5 | func TestNotRunMain(t *testing.T) { 6 | if mainDidRun { 7 | t.Error("main function did run") 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/otherpkg/otherpkg.go: -------------------------------------------------------------------------------- 1 | package otherpkg 2 | 3 | var Test float32 4 | -------------------------------------------------------------------------------- /tests/sort_test.go: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | import ( 4 | "sort" 5 | "testing" 6 | ) 7 | 8 | func TestSortSlice(t *testing.T) { 9 | a := [...]int{5, 4, 3, 2, 1} 10 | 11 | // Check for a subslice. 12 | s1 := a[1:4] 13 | sort.Slice(s1, func(i, j int) bool { return s1[i] < s1[j] }) 14 | if a != [...]int{5, 2, 3, 4, 1} { 15 | t.Fatal("not equal") 16 | } 17 | 18 | // Check a slice of the whole array. 19 | s2 := a[:] 20 | sort.Slice(s2, func(i, j int) bool { return s2[i] < s2[j] }) 21 | if a != [...]int{1, 2, 3, 4, 5} { 22 | t.Fatal("not equal") 23 | } 24 | 25 | // Try using a slice with cap. 26 | a2 := [...]int{6, 5, 4, 3, 2, 1} 27 | s3 := a2[1:4:4] 28 | sort.Slice(s3, func(i, j int) bool { return s3[i] < s3[j] }) 29 | if a2 != [...]int{6, 3, 4, 5, 2, 1} { 30 | t.Fatal("not equal") 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/testdata/time_inexternalization.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/gopherjs/gopherjs/js" 7 | ) 8 | 9 | var _ = time.Sleep // Force "time" package to be imported but let time.Time and time.Unix be DCEed since they're not used. 10 | 11 | func main() { 12 | // Excercise externalization of Go struct (with its special handling of time.Time). 13 | js.Global.Get("console").Call("log", struct{ S string }{"externalization ok"}) 14 | 15 | // Excercise internalization of JavaScript Date object (with its special handling of time.Time). 16 | date := js.Global.Get("Date").New("2015-08-29T20:56:00.869Z").Interface() 17 | js.Global.Set("myDate", date) 18 | js.Global.Get("console").Call("log", js.Global.Get("myDate").Call("toUTCString")) 19 | } 20 | -------------------------------------------------------------------------------- /tests/testdata/time_inexternalization.out: -------------------------------------------------------------------------------- 1 | { S: 'externalization ok' } 2 | Sat, 29 Aug 2015 20:56:00 GMT 3 | -------------------------------------------------------------------------------- /tool_deps.go: -------------------------------------------------------------------------------- 1 | // +build tools 2 | 3 | package tools 4 | 5 | import ( 6 | _ "github.com/shurcooL/vfsgen/cmd/vfsgendev" 7 | ) 8 | -------------------------------------------------------------------------------- /tools.go: -------------------------------------------------------------------------------- 1 | // +build tools 2 | 3 | package tools 4 | 5 | import ( 6 | _ "github.com/shurcooL/vfsgen/cmd/vfsgendev" 7 | ) 8 | --------------------------------------------------------------------------------