├── .github └── workflows │ ├── go112.yml │ ├── go113.yml │ ├── go114.yml │ ├── go115.yml │ └── go116.yml ├── .gitignore ├── .std_test_pkg_exclusions ├── LICENSE ├── README.md ├── build ├── build.go ├── build_test.go ├── go116_embed.go └── unchk_embed.go ├── circle.yml ├── 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 │ │ ├── archive │ │ └── tar │ │ │ └── tar_test.go │ │ ├── bufio │ │ └── bufio_test.go │ │ ├── bytes │ │ ├── bytes.go │ │ └── bytes_test.go │ │ ├── compress │ │ └── flate │ │ │ └── flate_test.go │ │ ├── crypto │ │ ├── internal │ │ │ └── subtle │ │ │ │ └── aliasing.go │ │ ├── rand │ │ │ └── rand.go │ │ └── x509 │ │ │ ├── root_darwin_test.go │ │ │ ├── root_js.go │ │ │ ├── verify.go │ │ │ ├── x509.go │ │ │ └── x509_test.go │ │ ├── database │ │ └── sql │ │ │ └── driver │ │ │ └── driver_test.go │ │ ├── debug │ │ └── elf │ │ │ └── elf_test.go │ │ ├── embed │ │ └── embed.go │ │ ├── encoding │ │ ├── gob │ │ │ └── gob_test.go │ │ └── json │ │ │ └── stream_test.go │ │ ├── fmt │ │ └── fmt_test.go │ │ ├── go │ │ ├── doc │ │ │ └── doc_test.go │ │ ├── parser │ │ │ └── parser_test.go │ │ └── token │ │ │ └── token_test.go │ │ ├── hash │ │ └── maphash │ │ │ └── maphash.go │ │ ├── html │ │ └── template │ │ │ ├── examplefiles_test.go │ │ │ └── template_test.go │ │ ├── internal │ │ ├── bytealg │ │ │ └── bytealg.go │ │ ├── cpu │ │ │ ├── cpu.go │ │ │ └── go116_cpu.go │ │ ├── fmtsort │ │ │ ├── fmtsort_test.go │ │ │ └── go116_fmtsort_test.go │ │ ├── poll │ │ │ ├── fd_poll.go │ │ │ └── go115_utils.go │ │ ├── reflectlite │ │ │ ├── all_test.go │ │ │ ├── export_test.go │ │ │ ├── reflect_mirror_test.go │ │ │ ├── reflectlite.go │ │ │ ├── swapper.go │ │ │ ├── type.go │ │ │ ├── utils.go │ │ │ └── value.go │ │ ├── syscall │ │ │ └── unix │ │ │ │ └── unix.go │ │ └── testenv │ │ │ └── testenv.go │ │ ├── io │ │ ├── io_test.go │ │ └── ioutil │ │ │ ├── go115_ioutil_test.go │ │ │ └── ioutil_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 │ │ ├── go116_os.go │ │ ├── os.go │ │ └── signal │ │ │ └── signal.go │ │ ├── path │ │ └── filepath │ │ │ ├── example_unix_walk_test.go │ │ │ └── filepath_test.go │ │ ├── reflect │ │ ├── go113_structof.go │ │ ├── go114_structof.go │ │ ├── go115_reflect_test.go │ │ ├── reflect.go │ │ ├── reflect_test.go │ │ └── swapper.go │ │ ├── regexp │ │ └── regexp_test.go │ │ ├── runtime │ │ ├── debug │ │ │ └── debug.go │ │ ├── go114_runtime.go │ │ ├── pprof │ │ │ └── pprof.go │ │ └── runtime.go │ │ ├── strings │ │ ├── strings.go │ │ └── strings_test.go │ │ ├── sync │ │ ├── atomic │ │ │ ├── atomic.go │ │ │ └── atomic_test.go │ │ ├── cond.go │ │ ├── export_test.go │ │ ├── go113_pool.go │ │ ├── go113_sync.go │ │ ├── pool.go │ │ ├── sync.go │ │ ├── sync_test.go │ │ └── waitgroup.go │ │ ├── syscall │ │ ├── go116_syscall_darwin.go │ │ ├── js │ │ │ ├── go112_js.go │ │ │ ├── go113_js.go │ │ │ ├── go114_js.go │ │ │ └── js.go │ │ ├── syscall.go │ │ ├── syscall_darwin_amd64.go │ │ ├── syscall_darwin_arm64.go │ │ ├── syscall_linux.go │ │ ├── syscall_nonlinux.go │ │ ├── syscall_unix.go │ │ └── syscall_windows.go │ │ ├── testing │ │ ├── example.go │ │ ├── go116_helper.go │ │ ├── ioutil.go │ │ └── testing.go │ │ ├── text │ │ └── template │ │ │ ├── examplefiles_test.go │ │ │ ├── template.go │ │ │ └── template_test.go │ │ ├── time │ │ ├── go114_timer.go │ │ ├── go115_timer.go │ │ ├── internal_test.go │ │ ├── time.go │ │ ├── time_test.go │ │ ├── timer.go │ │ └── zoneinfo.go │ │ ├── unicode │ │ └── unicode.go │ │ └── vendor │ │ └── golang.org │ │ └── x │ │ └── sys │ │ └── cpu │ │ └── cpu.go ├── package.go ├── prelude │ ├── genmin.go │ ├── goroutines.go │ ├── jsmapping.go │ ├── numeric.go │ ├── prelude.go │ ├── prelude_min.go │ ├── types.go │ └── uglifyjs_options.json ├── statements.go ├── typesutil │ └── typesutil.go ├── utils.go ├── vendor │ ├── github.com │ │ └── neelance │ │ │ └── astrewrite │ │ │ ├── LICENSE │ │ │ └── simplify.go │ └── vendor.json └── version.go ├── doc ├── packages.md └── syscalls.md ├── go.mod ├── go.sum ├── go116_testpkg.go ├── internal ├── goversion │ └── version.go └── 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.json ├── testpkg.go ├── tests ├── alias_test.go ├── copy_test.go ├── deferblock_test.go ├── doc.go ├── gopherjsvendored_test.sh ├── gorepo_test.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 │ ├── go113_js_test.go │ ├── go114_js_test.go │ └── js_test.go └── testdata │ ├── time_inexternalization.go │ └── time_inexternalization.out └── tool.go /.github/workflows/go112.yml: -------------------------------------------------------------------------------- 1 | name: Go1.12 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | 11 | test: 12 | name: Test on Go 1.12 13 | runs-on: ubuntu-latest 14 | steps: 15 | 16 | - name: Set up Go 1.12 17 | uses: actions/setup-go@v2 18 | with: 19 | go-version: 1.12 20 | 21 | - name: Setup Node.js environment 22 | uses: actions/setup-node@v2.1.2 23 | with: 24 | node-version: 10.0.0 25 | 26 | - name: Check out code into the Go module directory 27 | uses: actions/checkout@v2 28 | 29 | - name: Install GopherJS 30 | run: | 31 | npm install # Install our (dev) dependencies from package.json. 32 | cd node-syscall && ../node_modules/node-gyp/bin/node-gyp.js rebuild rebuild && mkdir -p ~/.node_libraries && cp build/Release/syscall.node ~/.node_libraries/syscall.node && cd .. 33 | export GO111MODULE="on" 34 | go install -v 35 | 36 | - name: Test GopherJS 37 | run: | 38 | diff -u <(echo -n) <(git status --porcelain) 39 | diff -u <(echo -n) <(gofmt -d .) 40 | go vet . # Go package in root directory. 41 | for d in */; do echo ./$d...; done | grep -v ./doc | grep -v ./tests | grep -v ./node | xargs go vet # All subdirectories except "doc", "tests", "node*". 42 | diff -u <(echo -n) <(go list ./compiler/natives/src/...) # All those packages should have // +build js. 43 | gopherjs install -v net/http # Should build successfully (can't run tests, since only client is supported). 44 | ulimit -s 10000 && gopherjs test --minify -v --short $(go list std | grep -v -f .std_test_pkg_exclusions) 45 | go test -v -race ./... 46 | gopherjs test -v fmt 47 | -------------------------------------------------------------------------------- /.github/workflows/go113.yml: -------------------------------------------------------------------------------- 1 | name: Go1.13 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | 11 | test: 12 | name: Test on Go 1.13 13 | runs-on: ubuntu-latest 14 | steps: 15 | 16 | - name: Set up Go 1.13 17 | uses: actions/setup-go@v2 18 | with: 19 | go-version: 1.13 20 | 21 | - name: Setup Node.js environment 22 | uses: actions/setup-node@v2.1.2 23 | with: 24 | node-version: 10.0.0 25 | 26 | - name: Check out code into the Go module directory 27 | uses: actions/checkout@v2 28 | 29 | - name: Install GopherJS 30 | run: | 31 | npm install # Install our (dev) dependencies from package.json. 32 | cd node-syscall && ../node_modules/node-gyp/bin/node-gyp.js rebuild rebuild && mkdir -p ~/.node_libraries && cp build/Release/syscall.node ~/.node_libraries/syscall.node && cd .. 33 | go install -v 34 | 35 | - name: Test GopherJS 36 | run: | 37 | diff -u <(echo -n) <(git status --porcelain) 38 | diff -u <(echo -n) <(gofmt -d .) 39 | go vet . # Go package in root directory. 40 | for d in */; do echo ./$d...; done | grep -v ./doc | grep -v ./tests | grep -v ./node | xargs go vet # All subdirectories except "doc", "tests", "node*". 41 | diff -u <(echo -n) <(go list ./compiler/natives/src/...) # All those packages should have // +build js. 42 | gopherjs install -v net/http # Should build successfully (can't run tests, since only client is supported). 43 | ulimit -s 10000 && gopherjs test --minify -v --short $(go list std | grep -v -f .std_test_pkg_exclusions) 44 | go test -v -race ./... 45 | gopherjs test -v fmt 46 | -------------------------------------------------------------------------------- /.github/workflows/go114.yml: -------------------------------------------------------------------------------- 1 | name: Go1.14 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | 11 | test: 12 | name: Test on Go 1.14 13 | runs-on: ubuntu-latest 14 | steps: 15 | 16 | - name: Set up Go 1.14 17 | uses: actions/setup-go@v2 18 | with: 19 | go-version: 1.14 20 | 21 | - name: Setup Node.js environment 22 | uses: actions/setup-node@v2.1.2 23 | with: 24 | node-version: 10.0.0 25 | 26 | - name: Check out code into the Go module directory 27 | uses: actions/checkout@v2 28 | 29 | - name: Install GopherJS 30 | run: | 31 | npm install # Install our (dev) dependencies from package.json. 32 | cd node-syscall && ../node_modules/node-gyp/bin/node-gyp.js rebuild rebuild && mkdir -p ~/.node_libraries && cp build/Release/syscall.node ~/.node_libraries/syscall.node && cd .. 33 | go install -v 34 | 35 | - name: Test GopherJS 36 | run: | 37 | diff -u <(echo -n) <(git status --porcelain) 38 | diff -u <(echo -n) <(gofmt -d .) 39 | go vet . # Go package in root directory. 40 | for d in */; do echo ./$d...; done | grep -v ./doc | grep -v ./tests | grep -v ./node | xargs go vet # All subdirectories except "doc", "tests", "node*". 41 | diff -u <(echo -n) <(go list ./compiler/natives/src/...) # All those packages should have // +build js. 42 | gopherjs install -v net/http # Should build successfully (can't run tests, since only client is supported). 43 | ulimit -s 10000 && gopherjs test --minify -v --short $(go list std | grep -v -f .std_test_pkg_exclusions) 44 | go test -v -race ./... 45 | gopherjs test -v fmt 46 | -------------------------------------------------------------------------------- /.github/workflows/go115.yml: -------------------------------------------------------------------------------- 1 | name: Go1.15 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | 11 | test: 12 | name: Test on Go 1.15 13 | runs-on: ubuntu-latest 14 | steps: 15 | 16 | - name: Set up Go 1.15 17 | uses: actions/setup-go@v2 18 | with: 19 | go-version: 1.15 20 | 21 | - name: Setup Node.js environment 22 | uses: actions/setup-node@v2.1.2 23 | with: 24 | node-version: 10.0.0 25 | 26 | - name: Check out code into the Go module directory 27 | uses: actions/checkout@v2 28 | 29 | - name: Install GopherJS 30 | run: | 31 | npm install # Install our (dev) dependencies from package.json. 32 | cd node-syscall && ../node_modules/node-gyp/bin/node-gyp.js rebuild rebuild && mkdir -p ~/.node_libraries && cp build/Release/syscall.node ~/.node_libraries/syscall.node && cd .. 33 | go install -v 34 | 35 | - name: Test GopherJS 36 | run: | 37 | diff -u <(echo -n) <(git status --porcelain) 38 | diff -u <(echo -n) <(gofmt -d .) 39 | go vet . # Go package in root directory. 40 | for d in */; do echo ./$d...; done | grep -v ./doc | grep -v ./tests | grep -v ./node | xargs go vet # All subdirectories except "doc", "tests", "node*". 41 | diff -u <(echo -n) <(go list ./compiler/natives/src/...) # All those packages should have // +build js. 42 | gopherjs install -v net/http # Should build successfully (can't run tests, since only client is supported). 43 | ulimit -s 10000 && gopherjs test --minify -v --short $(go list std | grep -v -f .std_test_pkg_exclusions) 44 | go test -v -race ./... 45 | gopherjs test -v fmt -------------------------------------------------------------------------------- /.github/workflows/go116.yml: -------------------------------------------------------------------------------- 1 | name: Go1.16 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | 11 | test: 12 | name: Test on Go 1.16 13 | runs-on: ubuntu-latest 14 | steps: 15 | 16 | - name: Set up Go 1.16 17 | uses: actions/setup-go@v2 18 | with: 19 | go-version: 1.16 20 | 21 | - name: Setup Node.js environment 22 | uses: actions/setup-node@v2.1.2 23 | with: 24 | node-version: 10.0.0 25 | 26 | - name: Check out code into the Go module directory 27 | uses: actions/checkout@v2 28 | 29 | - name: Install GopherJS 30 | run: | 31 | npm install # Install our (dev) dependencies from package.json. 32 | cd node-syscall && ../node_modules/node-gyp/bin/node-gyp.js rebuild rebuild && mkdir -p ~/.node_libraries && cp build/Release/syscall.node ~/.node_libraries/syscall.node && cd .. 33 | go install -v 34 | 35 | - name: Test GopherJS 36 | run: | 37 | diff -u <(echo -n) <(git status --porcelain) 38 | diff -u <(echo -n) <(gofmt -d .) 39 | go vet . # Go package in root directory. 40 | for d in */; do echo ./$d...; done | grep -v ./doc | grep -v ./tests | grep -v ./node | xargs go vet # All subdirectories except "doc", "tests", "node*". 41 | diff -u <(echo -n) <(go list ./compiler/natives/src/...) # All those packages should have // +build js. 42 | gopherjs install -v net/http # Should build successfully (can't run tests, since only client is supported). 43 | ulimit -s 10000 && gopherjs test --minify -v --short $(go list std | grep -v -f .std_test_pkg_exclusions) 44 | go test -v -race ./... 45 | gopherjs test -v fmt -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node-syscall/build 2 | /node_modules 3 | package-lock.json 4 | 5 | .idea/ 6 | gopherjs 7 | -------------------------------------------------------------------------------- /.std_test_pkg_exclusions: -------------------------------------------------------------------------------- 1 | context 2 | crypto 3 | crypto/internal/cipherhw 4 | crypto/tls 5 | crypto/x509/internal/macos 6 | crypto/x509/pkix 7 | crypto/ed25519 8 | crypto/ed25519/internal/edwards25519 9 | debug/gosym 10 | debug/plan9obj 11 | encoding 12 | go/build 13 | go/importer 14 | go/internal/gccgoimporter 15 | go/internal/gcimporter 16 | go/internal/srcimporter 17 | go/types 18 | hash 19 | image/color/palette 20 | image/internal/imageutil 21 | internal/cpu 22 | internal/goroot 23 | internal/nettrace 24 | internal/poll 25 | internal/race 26 | internal/singleflight 27 | internal/syscall/unix 28 | internal/syscall/windows 29 | internal/syscall/windows/registry 30 | internal/syscall/windows/sysdll 31 | internal/testenv 32 | internal/testlog 33 | internal/trace 34 | internal/x/net/nettest 35 | internal/unsafeheader 36 | internal/execabs 37 | log 38 | log/syslog 39 | net 40 | net/http 41 | net/http/cgi 42 | net/http/httptest 43 | net/http/httptrace 44 | net/http/httputil 45 | net/http/internal 46 | net/http/pprof 47 | net/internal/socktest 48 | net/rpc 49 | net/smtp 50 | os 51 | os/exec 52 | os/signal 53 | os/signal/internal/pty 54 | os/user 55 | plugin 56 | runtime 57 | runtime/cgo 58 | runtime/debug 59 | runtime/internal/atomic 60 | runtime/internal/math 61 | runtime/internal/sys 62 | runtime/pprof 63 | runtime/pprof/internal/profile 64 | runtime/race 65 | runtime/trace 66 | syscall 67 | testing 68 | testing/internal/testdeps 69 | testing/iotest 70 | unsafe 71 | vendor/golang.org/x/crypto/chacha20 72 | vendor/golang.org/x/crypto/chacha20poly1305 73 | vendor/golang.org/x/crypto/cryptobyte 74 | vendor/golang.org/x/crypto/cryptobyte/asn1 75 | vendor/golang.org/x/crypto/curve25519 76 | vendor/golang.org/x/crypto/hkdf 77 | vendor/golang.org/x/crypto/internal/chacha20 78 | vendor/golang.org/x/crypto/internal/subtle 79 | vendor/golang.org/x/crypto/poly1305 80 | vendor/golang.org/x/net/dns/dnsmessage 81 | vendor/golang.org/x/net/http/httpguts 82 | vendor/golang.org/x/net/http/httpproxy 83 | vendor/golang.org/x/net/http2/hpack 84 | vendor/golang.org/x/net/idna 85 | vendor/golang.org/x/net/nettest 86 | vendor/golang.org/x/net/route 87 | vendor/golang.org/x/sys/cpu 88 | vendor/golang.org/x/text/secure/bidirule 89 | vendor/golang.org/x/text/transform 90 | vendor/golang.org/x/text/unicode/bidi 91 | vendor/golang.org/x/text/unicode/norm 92 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /build/go116_embed.go: -------------------------------------------------------------------------------- 1 | // +build go1.16 2 | 3 | package build 4 | 5 | import ( 6 | "bytes" 7 | "fmt" 8 | "go/ast" 9 | "go/parser" 10 | "go/token" 11 | "strings" 12 | 13 | "github.com/visualfc/goembed" 14 | ) 15 | 16 | func buildIdent(name string) string { 17 | return fmt.Sprintf("__js_embed_%x__", name) 18 | } 19 | 20 | var embed_head = `package $pkg 21 | 22 | import ( 23 | "embed" 24 | _ "unsafe" 25 | ) 26 | 27 | //go:linkname gopherjs_embed_buildFS embed.buildFS 28 | func gopherjs_embed_buildFS(list []struct { 29 | name string 30 | data string 31 | hash [16]byte 32 | }) (f embed.FS) 33 | ` 34 | 35 | func (s *Session) checkEmbed(pkg *PackageData, fset *token.FileSet, files []*ast.File) (*ast.File, error) { 36 | if len(pkg.EmbedPatternPos) == 0 { 37 | return nil, nil 38 | } 39 | ems := goembed.CheckEmbed(pkg.EmbedPatternPos, fset, files) 40 | if len(ems) == 0 { 41 | return nil, nil 42 | } 43 | r := goembed.NewResolve() 44 | var buf bytes.Buffer 45 | buf.WriteString(strings.Replace(embed_head, "$pkg", pkg.Name, 1)) 46 | buf.WriteString("\nvar (\n") 47 | for _, v := range ems { 48 | v.Spec.Names[0].Name = "_" 49 | fs, _ := r.Load(pkg.Dir, v) 50 | switch v.Kind { 51 | case goembed.EmbedBytes: 52 | buf.WriteString(fmt.Sprintf("\t%v = []byte(%v)\n", v.Name, buildIdent(fs[0].Name))) 53 | case goembed.EmbedString: 54 | buf.WriteString(fmt.Sprintf("\t%v = %v\n", v.Name, buildIdent(fs[0].Name))) 55 | case goembed.EmbedFiles: 56 | fs = goembed.BuildFS(fs) 57 | buf.WriteString(fmt.Sprintf("\t%v=", v.Name)) 58 | buf.WriteString(`gopherjs_embed_buildFS( 59 | []struct { 60 | name string 61 | data string 62 | hash [16]byte 63 | }{ 64 | `) 65 | for _, f := range fs { 66 | if len(f.Data) == 0 { 67 | buf.WriteString(fmt.Sprintf("\t{\"%v\",\"\",[16]byte{}},\n", 68 | f.Name)) 69 | } else { 70 | buf.WriteString(fmt.Sprintf("\t{\"%v\",%v,[16]byte{%v}},\n", 71 | f.Name, buildIdent(f.Name), goembed.BytesToList(f.Hash[:]))) 72 | } 73 | } 74 | buf.WriteString("})\n") 75 | } 76 | } 77 | buf.WriteString("\n)\n") 78 | buf.WriteString("\nvar (\n") 79 | for _, f := range r.Files() { 80 | if len(f.Data) == 0 { 81 | buf.WriteString(fmt.Sprintf("\t%v string\n", 82 | buildIdent(f.Name))) 83 | } else { 84 | buf.WriteString(fmt.Sprintf("\t%v = string(\"%v\")\n", 85 | buildIdent(f.Name), goembed.BytesToHex(f.Data))) 86 | } 87 | } 88 | buf.WriteString(")\n\n") 89 | f, err := parser.ParseFile(fset, "js_embed.go", buf.String(), parser.ParseComments) 90 | if err != nil { 91 | return nil, err 92 | } 93 | return f, nil 94 | } 95 | -------------------------------------------------------------------------------- /build/unchk_embed.go: -------------------------------------------------------------------------------- 1 | // +build !go1.16 2 | 3 | package build 4 | 5 | import ( 6 | "go/ast" 7 | "go/token" 8 | ) 9 | 10 | func (s *Session) checkEmbed(pkg *PackageData, fileSet *token.FileSet, files []*ast.File) (*ast.File, error) { 11 | return nil, nil 12 | } 13 | -------------------------------------------------------------------------------- /circle.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | docker: 5 | - image: ubuntu:18.04 6 | environment: 7 | SOURCE_MAP_SUPPORT: false 8 | working_directory: ~/go/src/github.com/gopherjs/gopherjs 9 | steps: 10 | - run: apt-get update && apt-get install -y sudo curl git python make g++ 11 | - checkout 12 | - run: git clone https://github.com/creationix/nvm $HOME/.nvm && cd $HOME/.nvm && git checkout v0.33.9 && echo 'export NVM_DIR="$HOME/.nvm"' >> $BASH_ENV && echo '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' >> $BASH_ENV 13 | - run: nvm install 10.0.0 && nvm alias default 10.0.0 14 | - run: cd /usr/local && sudo rm -rf go && curl https://storage.googleapis.com/golang/go1.15.2.linux-amd64.tar.gz | sudo tar -xz 15 | - run: echo 'export PATH="$PATH:/usr/local/go/bin:$HOME/go/bin"' >> $BASH_ENV 16 | - run: go get -t -d -v ./... 17 | - run: go install -v 18 | - run: npm install # Install our (dev) dependencies from package.json. 19 | - run: cd node-syscall && ../node_modules/node-gyp/bin/node-gyp.js rebuild rebuild && mkdir -p ~/.node_libraries && cp build/Release/syscall.node ~/.node_libraries/syscall.node 20 | 21 | - run: go generate github.com/gopherjs/gopherjs/compiler/prelude 22 | - run: diff -u <(echo -n) <(git status --porcelain) 23 | - run: diff -u <(echo -n) <(gofmt -d .) 24 | - run: go vet . # Go package in root directory. 25 | - run: for d in */; do echo ./$d...; done | grep -v ./doc | grep -v ./tests | grep -v ./node | xargs go vet # All subdirectories except "doc", "tests", "node*". 26 | - run: diff -u <(echo -n) <(go list ./compiler/natives/src/...) # All those packages should have // +build js. 27 | - run: gopherjs install -v net/http # Should build successfully (can't run tests, since only client is supported). 28 | - run: ulimit -s 10000 && gopherjs test --minify -v --short github.com/gopherjs/gopherjs/tests/... $(go list std | grep -v -x -f .std_test_pkg_exclusions) 29 | - run: go test -v -race ./... 30 | - run: gopherjs test -v fmt # No minification should work. 31 | -------------------------------------------------------------------------------- /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/goplusjs/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 vfsgendev -source="github.com/goplusjs/gopherjs/compiler/gopherjspkg".FS -tag=gopherjsdev 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 | "path/filepath" 12 | 13 | "github.com/shurcooL/httpfs/filter" 14 | ) 15 | 16 | // FS is a virtual filesystem that contains core GopherJS packages. 17 | var FS = filter.Keep( 18 | http.Dir(importPathToDir("github.com/goplusjs/gopherjs")), 19 | func(path string, fi os.FileInfo) bool { 20 | return path == "/" || 21 | path == "/js" || (pathpkg.Dir(path) == "/js" && !fi.IsDir()) || 22 | path == "/nosync" || (pathpkg.Dir(path) == "/nosync" && !fi.IsDir()) 23 | }, 24 | ) 25 | 26 | func importPathToDir(importPath string) string { 27 | for _, src := range build.Default.SrcDirs() { 28 | dir := filepath.Join(src, importPath) 29 | if _, err := os.Stat(dir); err == nil { 30 | return dir 31 | } 32 | } 33 | p, err := build.Import(importPath, "", build.FindOnly) 34 | if err != nil { 35 | log.Fatalln(err) 36 | } 37 | return p.Dir 38 | } 39 | -------------------------------------------------------------------------------- /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 | import _ "github.com/shurcooL/vfsgen" 9 | 10 | //go:generate vfsgendev -source="github.com/goplusjs/gopherjs/compiler/natives".FS -tag=gopherjsdev 11 | -------------------------------------------------------------------------------- /compiler/natives/fs.go: -------------------------------------------------------------------------------- 1 | // +build gopherjsdev 2 | 3 | package natives 4 | 5 | import ( 6 | "fmt" 7 | "go/build" 8 | "log" 9 | "net/http" 10 | "os" 11 | "strings" 12 | 13 | "github.com/shurcooL/httpfs/filter" 14 | ) 15 | 16 | // FS is a virtual filesystem that contains native packages. 17 | var FS = filter.Keep( 18 | http.Dir(importPathToDir("github.com/goplusjs/gopherjs/compiler/natives")), 19 | func(path string, fi os.FileInfo) bool { 20 | return path == "/" || path == "/src" || strings.HasPrefix(path, "/src/") 21 | }, 22 | ) 23 | 24 | func importPathToDir(importPath string) string { 25 | p, err := build.Import(importPath, "", build.FindOnly) 26 | if err != nil { 27 | log.Fatalln(err) 28 | } 29 | fmt.Println("gopherjsdev importpath:", p.Dir) 30 | return p.Dir 31 | } 32 | -------------------------------------------------------------------------------- /compiler/natives/src/archive/tar/tar_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package tar 4 | 5 | import "testing" 6 | 7 | func TestFileInfoHeaderSymlink(t *testing.T) { 8 | t.Skip() 9 | } 10 | -------------------------------------------------------------------------------- /compiler/natives/src/bufio/bufio_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package bufio_test 4 | 5 | import ( 6 | "testing" 7 | ) 8 | 9 | func TestReadStringAllocs(t *testing.T) { 10 | t.Skip() 11 | } 12 | -------------------------------------------------------------------------------- /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/compress/flate/flate_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package flate 4 | 5 | import ( 6 | "testing" 7 | ) 8 | 9 | func TestBlockHuff(t *testing.T) { 10 | t.Skip() 11 | } 12 | -------------------------------------------------------------------------------- /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/root_darwin_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package x509 4 | 5 | var loadSystemRootsWithCgo func() (*CertPool, error) 6 | -------------------------------------------------------------------------------- /compiler/natives/src/crypto/x509/root_js.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package x509 4 | 5 | // Possible certificate files; stop after finding one. 6 | var certFiles = []string{} 7 | 8 | // Possible directories with certificate files; stop after successfully 9 | // reading at least one file from a directory. 10 | var certDirectories = []string{} 11 | -------------------------------------------------------------------------------- /compiler/natives/src/crypto/x509/verify.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package x509 4 | 5 | func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) { 6 | return nil, nil 7 | } 8 | -------------------------------------------------------------------------------- /compiler/natives/src/crypto/x509/x509.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package x509 4 | 5 | import ( 6 | "errors" 7 | ) 8 | 9 | func loadSystemRoots() (*CertPool, error) { 10 | return nil, errors.New("crypto/x509: system root pool is not available in GopherJS") 11 | } 12 | -------------------------------------------------------------------------------- /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/embed/embed.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | // +build go1.16 3 | 4 | package embed 5 | 6 | func buildFS(list []struct { 7 | name string 8 | data string 9 | hash [16]byte 10 | }) (f FS) { 11 | var files []file 12 | for _, v := range list { 13 | files = append(files, file{ 14 | name: v.name, 15 | data: v.data, 16 | hash: v.hash, 17 | }) 18 | } 19 | f.files = &files 20 | return 21 | } 22 | -------------------------------------------------------------------------------- /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/doc/doc_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package doc 4 | 5 | import ( 6 | "testing" 7 | ) 8 | 9 | func Test(t *testing.T) { 10 | t.Skip() 11 | } 12 | -------------------------------------------------------------------------------- /compiler/natives/src/go/parser/parser_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package parser 4 | 5 | import ( 6 | "testing" 7 | ) 8 | 9 | func TestErrors(t *testing.T) { 10 | t.Skip() 11 | } 12 | 13 | func TestParseDir(t *testing.T) { 14 | t.Skip() 15 | } 16 | -------------------------------------------------------------------------------- /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/hash/maphash/maphash.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | // +build go1.14 3 | 4 | package maphash 5 | 6 | import _ "unsafe" 7 | 8 | //go:linkname memhash_init runtime.memhash_init 9 | func memhash_init() 10 | 11 | func init() { 12 | memhash_init() 13 | } 14 | -------------------------------------------------------------------------------- /compiler/natives/src/html/template/examplefiles_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package template_test 4 | 5 | import ( 6 | "fmt" 7 | ) 8 | 9 | func ExampleTemplate_glob() { 10 | fmt.Print("T0 invokes T1: (T1 invokes T2: (This is T2))") 11 | // Output: 12 | // T0 invokes T1: (T1 invokes T2: (This is T2)) 13 | } 14 | 15 | func ExampleTemplate_helpers() { 16 | fmt.Print("Driver 1 calls T1: (T1 invokes T2: (This is T2))\nDriver 2 calls T2: (This is T2)") 17 | // Output: 18 | // Driver 1 calls T1: (T1 invokes T2: (This is T2)) 19 | // Driver 2 calls T2: (This is T2) 20 | } 21 | 22 | func ExampleTemplate_share() { 23 | fmt.Print("T0 (second version) invokes T1: (T1 invokes T2: (T2, version B))\nT0 (first version) invokes T1: (T1 invokes T2: (T2, version A))") 24 | // Output: 25 | // T0 (second version) invokes T1: (T1 invokes T2: (T2, version B)) 26 | // T0 (first version) invokes T1: (T1 invokes T2: (T2, version A)) 27 | } 28 | 29 | func ExampleTemplate_parsefiles() { 30 | fmt.Print("T1 invokes T2: (This is T2)") 31 | // Output: 32 | // T1 invokes T2: (This is T2) 33 | } 34 | -------------------------------------------------------------------------------- /compiler/natives/src/html/template/template_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package template 4 | 5 | import ( 6 | "testing" 7 | ) 8 | 9 | func TestParseGlob(t *testing.T) { 10 | t.Skip() 11 | } 12 | 13 | func TestParseGlobWithData(t *testing.T) { 14 | t.Skip() 15 | } 16 | -------------------------------------------------------------------------------- /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 ( 6 | CacheLineSize = 0 7 | CacheLinePadSize = 0 8 | ) 9 | -------------------------------------------------------------------------------- /compiler/natives/src/internal/cpu/go116_cpu.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | // +build go1.16 3 | 4 | package cpu 5 | 6 | func doinit() { 7 | } 8 | -------------------------------------------------------------------------------- /compiler/natives/src/internal/fmtsort/fmtsort_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | // +build !go1.16 3 | 4 | package fmtsort_test 5 | 6 | import ( 7 | "math" 8 | "reflect" 9 | "testing" 10 | 11 | "internal/fmtsort" 12 | ) 13 | 14 | // needsSkip reports whether the kind doesn't work for sorting on GopherJS. 15 | func needsSkip(k reflect.Kind) bool { 16 | switch k { 17 | case reflect.Ptr, reflect.Chan: 18 | return true 19 | } 20 | return false 21 | } 22 | 23 | // Note: sync with the original TestCompare. 24 | func TestCompare(t *testing.T) { 25 | for _, test := range compareTests { 26 | for i, v0 := range test { 27 | for j, v1 := range test { 28 | if needsSkip(v0.Kind()) { 29 | continue 30 | } 31 | if needsSkip(v1.Kind()) { 32 | continue 33 | } 34 | 35 | c := fmtsort.Compare(v0, v1) 36 | var expect int 37 | switch { 38 | case i == j: 39 | expect = 0 40 | // NaNs are tricky. 41 | if typ := v0.Type(); (typ.Kind() == reflect.Float32 || typ.Kind() == reflect.Float64) && math.IsNaN(v0.Float()) { 42 | expect = -1 43 | } 44 | case i < j: 45 | expect = -1 46 | case i > j: 47 | expect = 1 48 | } 49 | if c != expect { 50 | t.Errorf("%s: compare(%v,%v)=%d; expect %d", v0.Type(), v0, v1, c, expect) 51 | } 52 | } 53 | } 54 | } 55 | } 56 | 57 | func TestOrder(t *testing.T) { 58 | t.Skip("known issue: nil key doesn't work") 59 | } 60 | -------------------------------------------------------------------------------- /compiler/natives/src/internal/fmtsort/go116_fmtsort_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | // +build go1.16 3 | 4 | package fmtsort_test 5 | 6 | import ( 7 | "reflect" 8 | "testing" 9 | ) 10 | 11 | func ct(typ reflect.Type, args ...interface{}) []reflect.Value { 12 | return nil 13 | } 14 | 15 | func TestCompare(t *testing.T) { 16 | t.Skip("known issue: unsafe.Pointer doesn't support") 17 | } 18 | 19 | func TestOrder(t *testing.T) { 20 | t.Skip("known issue: nil key doesn't work") 21 | } 22 | -------------------------------------------------------------------------------- /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/poll/go115_utils.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | // +build go1.15 3 | 4 | package poll 5 | 6 | import ( 7 | "errors" 8 | ) 9 | 10 | var ( 11 | ErrTimeout = errors.New("timeout") 12 | ) 13 | -------------------------------------------------------------------------------- /compiler/natives/src/internal/reflectlite/all_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package reflectlite_test 4 | 5 | import ( 6 | . "internal/reflectlite" 7 | "testing" 8 | ) 9 | 10 | func TestTypes(t *testing.T) { 11 | for i, tt := range typeTests { 12 | if i == 30 { 13 | continue 14 | } 15 | testReflectType(t, i, Field(ValueOf(tt.i), 0).Type(), tt.s) 16 | } 17 | } 18 | 19 | func TestNameBytesAreAligned(t *testing.T) { 20 | t.Skip("TestNameBytesAreAligned") 21 | } 22 | -------------------------------------------------------------------------------- /compiler/natives/src/internal/reflectlite/export_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package reflectlite 4 | 5 | import ( 6 | "unsafe" 7 | ) 8 | 9 | // Field returns the i'th field of the struct v. 10 | // It panics if v's Kind is not Struct or i is out of range. 11 | func Field(v Value, i int) Value { 12 | if v.kind() != Struct { 13 | panic(&ValueError{"reflect.Value.Field", v.kind()}) 14 | } 15 | return v.Field(i) 16 | } 17 | 18 | func TField(typ Type, i int) Type { 19 | t := typ.(*rtype) 20 | if t.Kind() != Struct { 21 | panic("reflect: Field of non-struct type") 22 | } 23 | tt := (*structType)(unsafe.Pointer(t)) 24 | return StructFieldType(tt, i) 25 | } 26 | 27 | // Field returns the i'th struct field. 28 | func StructFieldType(t *structType, i int) Type { 29 | if i < 0 || i >= len(t.fields) { 30 | panic("reflect: Field index out of bounds") 31 | } 32 | p := &t.fields[i] 33 | return toType(p.typ) 34 | } 35 | 36 | // // Zero returns a Value representing the zero value for the specified type. 37 | // // The result is different from the zero value of the Value struct, 38 | // // which represents no value at all. 39 | // // For example, Zero(TypeOf(42)) returns a Value with Kind Int and value 0. 40 | // // The returned value is neither addressable nor settable. 41 | // func Zero(typ Type) Value { 42 | // if typ == nil { 43 | // panic("reflect: Zero(nil)") 44 | // } 45 | // t := typ.(*rtype) 46 | // fl := flag(t.Kind()) 47 | // if ifaceIndir(t) { 48 | // return Value{t, unsafe_New(t), fl | flagIndir} 49 | // } 50 | // return Value{t, nil, fl} 51 | // } 52 | 53 | // // ToInterface returns v's current value as an interface{}. 54 | // // It is equivalent to: 55 | // // var i interface{} = (v's underlying value) 56 | // // It panics if the Value was obtained by accessing 57 | // // unexported struct fields. 58 | // func ToInterface(v Value) (i interface{}) { 59 | // return valueInterface(v) 60 | // } 61 | 62 | // type EmbedWithUnexpMeth struct{} 63 | 64 | // func (EmbedWithUnexpMeth) f() {} 65 | 66 | // type pinUnexpMeth interface { 67 | // f() 68 | // } 69 | 70 | // var pinUnexpMethI = pinUnexpMeth(EmbedWithUnexpMeth{}) 71 | 72 | // func FirstMethodNameBytes(t Type) *byte { 73 | // _ = pinUnexpMethI 74 | 75 | // ut := t.uncommon() 76 | // if ut == nil { 77 | // panic("type has no methods") 78 | // } 79 | // m := ut.methods()[0] 80 | // mname := t.(*rtype).nameOff(m.name) 81 | // if *mname.data(0, "name flag field")&(1<<2) == 0 { 82 | // panic("method name does not have pkgPath *string") 83 | // } 84 | // return mname.bytes 85 | // } 86 | 87 | // type Buffer struct { 88 | // buf []byte 89 | // } 90 | -------------------------------------------------------------------------------- /compiler/natives/src/internal/reflectlite/reflect_mirror_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package reflectlite_test 4 | 5 | import ( 6 | "testing" 7 | ) 8 | 9 | func TestMirrorWithReflect(t *testing.T) { 10 | t.Skip("TestMirrorWithReflect") 11 | } 12 | -------------------------------------------------------------------------------- /compiler/natives/src/internal/reflectlite/swapper.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package reflectlite 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/internal/reflectlite/type.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package reflectlite 4 | 5 | import ( 6 | "unsafe" 7 | 8 | "github.com/gopherjs/gopherjs/js" 9 | ) 10 | 11 | func (t *rtype) Comparable() bool { 12 | switch t.Kind() { 13 | case Func, Slice, Map: 14 | return false 15 | case Array: 16 | return t.Elem().Comparable() 17 | case Struct: 18 | for i := 0; i < t.NumField(); i++ { 19 | ft := t.Field(i) 20 | if !ft.typ.Comparable() { 21 | return false 22 | } 23 | } 24 | } 25 | return true 26 | } 27 | 28 | func (t *rtype) IsVariadic() bool { 29 | if t.Kind() != Func { 30 | panic("reflect: IsVariadic of non-func type") 31 | } 32 | tt := (*funcType)(unsafe.Pointer(t)) 33 | return tt.outCount&(1<<15) != 0 34 | } 35 | 36 | func (t *rtype) kindType() *rtype { 37 | return (*rtype)(unsafe.Pointer(js.InternalObject(t).Get(idKindType))) 38 | } 39 | 40 | func (t *rtype) Field(i int) structField { 41 | if t.Kind() != Struct { 42 | panic("reflect: Field of non-struct type") 43 | } 44 | tt := (*structType)(unsafe.Pointer(t)) 45 | if i < 0 || i >= len(tt.fields) { 46 | panic("reflect: Field index out of bounds") 47 | } 48 | return tt.fields[i] 49 | } 50 | 51 | func (t *rtype) Key() Type { 52 | if t.Kind() != Map { 53 | panic("reflect: Key of non-map type") 54 | } 55 | tt := (*mapType)(unsafe.Pointer(t)) 56 | return toType(tt.key) 57 | } 58 | 59 | func (t *rtype) NumField() int { 60 | if t.Kind() != Struct { 61 | panic("reflect: NumField of non-struct type") 62 | } 63 | tt := (*structType)(unsafe.Pointer(t)) 64 | return len(tt.fields) 65 | } 66 | 67 | func (t *rtype) Method(i int) (m Method) { 68 | if t.Kind() == Interface { 69 | tt := (*interfaceType)(unsafe.Pointer(t)) 70 | return tt.Method(i) 71 | } 72 | methods := t.exportedMethods() 73 | if i < 0 || i >= len(methods) { 74 | panic("reflect: Method index out of range") 75 | } 76 | p := methods[i] 77 | pname := t.nameOff(p.name) 78 | m.Name = pname.name() 79 | fl := flag(Func) 80 | mtyp := t.typeOff(p.mtyp) 81 | ft := (*funcType)(unsafe.Pointer(mtyp)) 82 | in := make([]Type, 0, 1+len(ft.in())) 83 | in = append(in, t) 84 | for _, arg := range ft.in() { 85 | in = append(in, arg) 86 | } 87 | out := make([]Type, 0, len(ft.out())) 88 | for _, ret := range ft.out() { 89 | out = append(out, ret) 90 | } 91 | mt := FuncOf(in, out, ft.IsVariadic()) 92 | m.Type = mt 93 | prop := js.Global.Call("$methodSet", js.InternalObject(t).Get(idJsType)).Index(i).Get("prop").String() 94 | fn := js.MakeFunc(func(this *js.Object, arguments []*js.Object) interface{} { 95 | rcvr := arguments[0] 96 | return rcvr.Get(prop).Call("apply", rcvr, arguments[1:]) 97 | }) 98 | m.Func = Value{mt.(*rtype), unsafe.Pointer(fn.Unsafe()), fl} 99 | 100 | m.Index = i 101 | return m 102 | } 103 | -------------------------------------------------------------------------------- /compiler/natives/src/internal/reflectlite/utils.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package reflectlite 4 | 5 | import ( 6 | "unsafe" 7 | ) 8 | 9 | type ChanDir int 10 | 11 | const ( 12 | RecvDir ChanDir = 1 << iota // <-chan 13 | SendDir // chan<- 14 | BothDir = RecvDir | SendDir // chan 15 | ) 16 | 17 | type errorString struct { 18 | s string 19 | } 20 | 21 | func (e *errorString) Error() string { 22 | return e.s 23 | } 24 | 25 | var ( 26 | ErrSyntax = &errorString{"invalid syntax"} 27 | ) 28 | 29 | func unquote(s string) (string, error) { 30 | if len(s) < 2 { 31 | return s, nil 32 | } 33 | if s[0] == '\'' || s[0] == '"' { 34 | if s[len(s)-1] == s[0] { 35 | return s[1 : len(s)-1], nil 36 | } 37 | return "", ErrSyntax 38 | } 39 | return s, nil 40 | } 41 | 42 | // Method represents a single method. 43 | type Method struct { 44 | // Name is the method name. 45 | // PkgPath is the package path that qualifies a lower case (unexported) 46 | // method name. It is empty for upper case (exported) method names. 47 | // The combination of PkgPath and Name uniquely identifies a method 48 | // in a method set. 49 | // See https://golang.org/ref/spec#Uniqueness_of_identifiers 50 | Name string 51 | PkgPath string 52 | 53 | Type Type // method type 54 | Func Value // func with receiver as first argument 55 | Index int // index for Type.Method 56 | } 57 | 58 | // A SelectDir describes the communication direction of a select case. 59 | type SelectDir int 60 | 61 | // NOTE: These values must match ../runtime/select.go:/selectDir. 62 | 63 | const ( 64 | _ SelectDir = iota 65 | SelectSend // case Chan <- Send 66 | SelectRecv // case <-Chan: 67 | SelectDefault // default 68 | ) 69 | 70 | // A runtimeSelect is a single case passed to rselect. 71 | // This must match ../runtime/select.go:/runtimeSelect 72 | type runtimeSelect struct { 73 | dir SelectDir // SelectSend, SelectRecv or SelectDefault 74 | typ *rtype // channel type 75 | ch unsafe.Pointer // channel 76 | val unsafe.Pointer // ptr to data (SendDir) or ptr to receive buffer (RecvDir) 77 | } 78 | 79 | func (f flag) mustBe(expected Kind) { 80 | // TODO(mvdan): use f.kind() again once mid-stack inlining gets better 81 | if Kind(f&flagKindMask) != expected { 82 | panic(&ValueError{methodName(), f.kind()}) 83 | } 84 | } 85 | 86 | // A StructTag is the tag string in a struct field. 87 | // 88 | // By convention, tag strings are a concatenation of 89 | // optionally space-separated key:"value" pairs. 90 | // Each key is a non-empty string consisting of non-control 91 | // characters other than space (U+0020 ' '), quote (U+0022 '"'), 92 | // and colon (U+003A ':'). Each value is quoted using U+0022 '"' 93 | // characters and Go string literal syntax. 94 | type StructTag string 95 | 96 | func typesMustMatch(what string, t1, t2 Type) { 97 | if t1 != t2 { 98 | panic(what + ": " + t1.String() + " != " + t2.String()) 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /compiler/natives/src/internal/syscall/unix/unix.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package unix 4 | 5 | const ( 6 | randomTrap = 0 7 | fstatatTrap = 0 8 | getrandomTrap uintptr = 0 9 | copyFileRangeTrap uintptr = 0 10 | ) 11 | 12 | func IsNonblock(fd int) (nonblocking bool, err error) { 13 | return false, nil 14 | } 15 | -------------------------------------------------------------------------------- /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 | 25 | func TestCopyLargeWriter(t *testing.T) { 26 | t.Skip("known issue: unsupport hides interface") 27 | } 28 | -------------------------------------------------------------------------------- /compiler/natives/src/io/ioutil/go115_ioutil_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | // +build go1.15 3 | 4 | package ioutil_test 5 | 6 | import ( 7 | "testing" 8 | ) 9 | 10 | func TestReadDir(t *testing.T) { 11 | t.Skip() 12 | } 13 | 14 | func TestReadOnlyWriteFile(t *testing.T) { 15 | t.Skip() 16 | } 17 | 18 | func TestTempDir_BadPattern(t *testing.T) { 19 | t.Skip() 20 | } 21 | 22 | func TestTempDir(t *testing.T) { 23 | t.Skip() 24 | } 25 | 26 | func TestTempFile_BadPattern(t *testing.T) { 27 | t.Skip() 28 | } 29 | 30 | func TestTempFile_pattern(t *testing.T) { 31 | t.Skip() 32 | } 33 | -------------------------------------------------------------------------------- /compiler/natives/src/io/ioutil/ioutil_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | // +build !go1.15 3 | 4 | package ioutil 5 | 6 | import ( 7 | "testing" 8 | ) 9 | 10 | func TestReadDir(t *testing.T) { 11 | t.Skip() 12 | } 13 | 14 | func TestReadOnlyWriteFile(t *testing.T) { 15 | t.Skip() 16 | } 17 | 18 | func TestTempDir_BadPattern(t *testing.T) { 19 | t.Skip() 20 | } 21 | 22 | func TestTempDir(t *testing.T) { 23 | t.Skip() 24 | } 25 | 26 | func TestTempFile_BadPattern(t *testing.T) { 27 | t.Skip() 28 | } 29 | 30 | func TestTempFile_pattern(t *testing.T) { 31 | t.Skip() 32 | } 33 | -------------------------------------------------------------------------------- /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 | 15 | func TetSqr(t *testing.T) { 16 | t.Skip("slow") 17 | } 18 | 19 | func TestNatDiv(t *testing.T) { 20 | t.Skip("slow") 21 | } 22 | -------------------------------------------------------------------------------- /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/go116_os.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | // +build go1.16 3 | 4 | package os 5 | 6 | const isBigEndian = false 7 | -------------------------------------------------------------------------------- /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 | //go:linkname fastrand runtime.fastrand 12 | func fastrand() uint32 13 | 14 | func runtime_args() []string { // not called on Windows 15 | return Args 16 | } 17 | 18 | func init() { 19 | if process := js.Global.Get("process"); process != js.Undefined { 20 | argv := process.Get("argv") 21 | Args = make([]string, argv.Length()-1) 22 | for i := 0; i < argv.Length()-1; i++ { 23 | Args[i] = argv.Index(i + 1).String() 24 | } 25 | } 26 | if len(Args) == 0 { 27 | Args = []string{"?"} 28 | } 29 | } 30 | 31 | func runtime_beforeExit() {} 32 | 33 | func executable() (string, error) { 34 | return "", errors.New("Executable not implemented for GOARCH=js") 35 | } 36 | -------------------------------------------------------------------------------- /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/path/filepath/example_unix_walk_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | // +build !windows,!plan9 3 | 4 | package filepath_test 5 | 6 | import ( 7 | "fmt" 8 | ) 9 | 10 | func ExampleWalk() { 11 | fmt.Print(`On Unix: 12 | visited file or dir: "." 13 | visited file or dir: "dir" 14 | visited file or dir: "dir/to" 15 | visited file or dir: "dir/to/walk" 16 | skipping a dir without errors: skip`) 17 | // Output: 18 | // On Unix: 19 | // visited file or dir: "." 20 | // visited file or dir: "dir" 21 | // visited file or dir: "dir/to" 22 | // visited file or dir: "dir/to/walk" 23 | // skipping a dir without errors: skip 24 | } 25 | -------------------------------------------------------------------------------- /compiler/natives/src/path/filepath/filepath_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package filepath_test 4 | 5 | import ( 6 | "testing" 7 | ) 8 | 9 | func TestGlob(t *testing.T) { 10 | t.Skip() 11 | } 12 | 13 | func TestGlobError(t *testing.T) { 14 | t.Skip() 15 | } 16 | 17 | func TestGlobUNC(t *testing.T) { 18 | t.Skip() 19 | } 20 | 21 | func TestNonWindowsGlobEscape(t *testing.T) { 22 | t.Skip() 23 | } 24 | 25 | func TestGlobSymlink(t *testing.T) { 26 | t.Skip() 27 | } 28 | 29 | func TestWalk(t *testing.T) { 30 | t.Skip() 31 | } 32 | 33 | func TestWalkSkipDirOnFile(t *testing.T) { 34 | t.Skip() 35 | } 36 | 37 | func TestWalkFileError(t *testing.T) { 38 | t.Skip() 39 | } 40 | 41 | func TestEvalSymlinks(t *testing.T) { 42 | t.Skip() 43 | } 44 | 45 | func TestEvalSymlinksIsNotExist(t *testing.T) { 46 | t.Skip() 47 | } 48 | 49 | func TestAbs(t *testing.T) { 50 | t.Skip() 51 | } 52 | 53 | func TestAbsEmptyString(t *testing.T) { 54 | t.Skip() 55 | } 56 | 57 | func TestBug3486(t *testing.T) { 58 | t.Skip() 59 | } 60 | 61 | func TestWalkSymlink(t *testing.T) { 62 | t.Skip() 63 | } 64 | 65 | func TestIssue29372(t *testing.T) { 66 | t.Skip() 67 | } 68 | 69 | func TestIssue13582(t *testing.T) { 70 | t.Skip() 71 | } 72 | 73 | func TestEvalSymlinksAboveRoot(t *testing.T) { 74 | t.Skip() 75 | } 76 | 77 | func TestEvalSymlinksAboveRootChdir(t *testing.T) { 78 | t.Skip() 79 | } 80 | -------------------------------------------------------------------------------- /compiler/natives/src/reflect/go113_structof.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | // +build !go1.14 3 | 4 | package reflect 5 | 6 | import ( 7 | "strconv" 8 | "unsafe" 9 | 10 | "github.com/gopherjs/gopherjs/js" 11 | ) 12 | 13 | func StructOf(fields []StructField) Type { 14 | var ( 15 | jsFields = make([]*js.Object, len(fields)) 16 | fset = map[string]struct{}{} 17 | hasGCProg bool 18 | ) 19 | for i, field := range fields { 20 | if field.Name == "" { 21 | panic("reflect.StructOf: field " + strconv.Itoa(i) + " has no name") 22 | } 23 | if !isValidFieldName(field.Name) { 24 | panic("reflect.StructOf: field " + strconv.Itoa(i) + " has invalid name") 25 | } 26 | if field.Type == nil { 27 | panic("reflect.StructOf: field " + strconv.Itoa(i) + " has no type") 28 | } 29 | f := runtimeStructField(field) 30 | ft := f.typ 31 | if ft.kind&kindGCProg != 0 { 32 | hasGCProg = true 33 | } 34 | 35 | name := field.Name 36 | if f.embedded() { 37 | // Embedded field 38 | if f.typ.Kind() == Ptr { 39 | // Embedded ** and *interface{} are illegal 40 | elem := ft.Elem() 41 | if k := elem.Kind(); k == Ptr || k == Interface { 42 | panic("reflect.StructOf: illegal embedded field type " + ft.String()) 43 | } 44 | } 45 | 46 | switch f.typ.Kind() { 47 | case Interface: 48 | ift := (*interfaceType)(unsafe.Pointer(ft)) 49 | for _, m := range ift.methods { 50 | if ift.nameOff(m.name).pkgPath() != "" { 51 | // TODO(sbinet). Issue 15924. 52 | panic("reflect: embedded interface with unexported method(s) not implemented") 53 | } 54 | } 55 | case Ptr: 56 | ptr := (*ptrType)(unsafe.Pointer(ft)) 57 | if unt := ptr.uncommon(); unt != nil { 58 | if i > 0 && unt.mcount > 0 { 59 | // Issue 15924. 60 | panic("reflect: embedded type with methods not implemented if type is not first field") 61 | } 62 | if len(fields) > 1 { 63 | panic("reflect: embedded type with methods not implemented if there is more than one field") 64 | } 65 | for _, m := range unt.methods() { 66 | mname := ptr.nameOff(m.name) 67 | if mname.pkgPath() != "" { 68 | // TODO(sbinet). 69 | // Issue 15924. 70 | panic("reflect: embedded interface with unexported method(s) not implemented") 71 | } 72 | } 73 | } 74 | if unt := ptr.elem.uncommon(); unt != nil { 75 | for _, m := range unt.methods() { 76 | mname := ptr.nameOff(m.name) 77 | if mname.pkgPath() != "" { 78 | // TODO(sbinet) 79 | // Issue 15924. 80 | panic("reflect: embedded interface with unexported method(s) not implemented") 81 | } 82 | } 83 | } 84 | default: 85 | if unt := ft.uncommon(); unt != nil { 86 | if i > 0 && unt.mcount > 0 { 87 | // Issue 15924. 88 | panic("reflect: embedded type with methods not implemented if type is not first field") 89 | } 90 | if len(fields) > 1 && ft.kind&kindDirectIface != 0 { 91 | panic("reflect: embedded type with methods not implemented for non-pointer type") 92 | } 93 | for _, m := range unt.methods() { 94 | mname := ft.nameOff(m.name) 95 | if mname.pkgPath() != "" { 96 | // TODO(sbinet) 97 | // Issue 15924. 98 | panic("reflect: embedded interface with unexported method(s) not implemented") 99 | } 100 | } 101 | } 102 | } 103 | } 104 | if _, dup := fset[name]; dup { 105 | panic("reflect.StructOf: duplicate field " + name) 106 | } 107 | fset[name] = struct{}{} 108 | jsf := js.Global.Get("Object").New() 109 | jsf.Set("prop", name) 110 | jsf.Set("name", name) 111 | jsf.Set("exported", f.name.isExported()) 112 | jsf.Set("typ", jsType(field.Type)) 113 | jsf.Set("tag", field.Tag) 114 | jsf.Set("embedded", field.Anonymous) 115 | jsFields[i] = jsf 116 | } 117 | _ = hasGCProg 118 | typ := js.Global.Call("$structType", "", jsFields) 119 | return _reflectType(typ, objstr) 120 | } 121 | 122 | func objstr(obj *js.Object) string { 123 | return obj.String() 124 | } 125 | -------------------------------------------------------------------------------- /compiler/natives/src/reflect/go114_structof.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | // +build go1.14 3 | 4 | package reflect 5 | 6 | import ( 7 | "strconv" 8 | "unsafe" 9 | 10 | "github.com/gopherjs/gopherjs/js" 11 | ) 12 | 13 | func StructOf(fields []StructField) Type { 14 | var ( 15 | jsFields = make([]*js.Object, len(fields)) 16 | fset = map[string]struct{}{} 17 | pkgpath string 18 | hasGCProg bool 19 | ) 20 | for i, field := range fields { 21 | if field.Name == "" { 22 | panic("reflect.StructOf: field " + strconv.Itoa(i) + " has no name") 23 | } 24 | if !isValidFieldName(field.Name) { 25 | panic("reflect.StructOf: field " + strconv.Itoa(i) + " has invalid name") 26 | } 27 | if field.Type == nil { 28 | panic("reflect.StructOf: field " + strconv.Itoa(i) + " has no type") 29 | } 30 | f, fpkgpath := runtimeStructField(field) 31 | ft := f.typ 32 | if ft.kind&kindGCProg != 0 { 33 | hasGCProg = true 34 | } 35 | if fpkgpath != "" { 36 | if pkgpath == "" { 37 | pkgpath = fpkgpath 38 | } else if pkgpath != fpkgpath { 39 | panic("reflect.Struct: fields with different PkgPath " + pkgpath + " and " + fpkgpath) 40 | } 41 | } 42 | name := field.Name 43 | if f.embedded() { 44 | // Embedded field 45 | if field.Type.Kind() == Ptr { 46 | // Embedded ** and *interface{} are illegal 47 | elem := field.Type.Elem() 48 | if k := elem.Kind(); k == Ptr || k == Interface { 49 | panic("reflect.StructOf: illegal anonymous field type " + field.Type.String()) 50 | } 51 | } 52 | switch field.Type.Kind() { 53 | case Interface: 54 | case Ptr: 55 | ptr := (*ptrType)(unsafe.Pointer(ft)) 56 | if unt := ptr.uncommon(); unt != nil { 57 | if i > 0 && unt.mcount > 0 { 58 | // Issue 15924. 59 | panic("reflect: embedded type with methods not implemented if type is not first field") 60 | } 61 | if len(fields) > 1 { 62 | panic("reflect: embedded type with methods not implemented if there is more than one field") 63 | } 64 | } 65 | default: 66 | if unt := ft.uncommon(); unt != nil { 67 | if i > 0 && unt.mcount > 0 { 68 | // Issue 15924. 69 | panic("reflect: embedded type with methods not implemented if type is not first field") 70 | } 71 | if len(fields) > 1 && ft.kind&kindDirectIface != 0 { 72 | panic("reflect: embedded type with methods not implemented for non-pointer type") 73 | } 74 | } 75 | } 76 | } 77 | 78 | if _, dup := fset[name]; dup { 79 | panic("reflect.StructOf: duplicate field " + name) 80 | } 81 | fset[name] = struct{}{} 82 | jsf := js.Global.Get("Object").New() 83 | jsf.Set("prop", name) 84 | jsf.Set("name", name) 85 | jsf.Set("exported", f.name.isExported()) 86 | jsf.Set("typ", jsType(field.Type)) 87 | jsf.Set("tag", field.Tag) 88 | jsf.Set("embedded", field.Anonymous) 89 | jsFields[i] = jsf 90 | } 91 | _ = hasGCProg 92 | typ := js.Global.Call("$structType", "", jsFields) 93 | if pkgpath != "" { 94 | typ.Set("pkgPath", pkgpath) 95 | } 96 | return _reflectType(typ, objstr) 97 | } 98 | 99 | func objstr(obj *js.Object) string { 100 | return obj.String() 101 | } 102 | -------------------------------------------------------------------------------- /compiler/natives/src/reflect/go115_reflect_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | // +build go1.15 3 | 4 | package reflect_test 5 | 6 | import ( 7 | "fmt" 8 | . "reflect" 9 | "strings" 10 | "testing" 11 | ) 12 | 13 | func TestConvertNaNs(t *testing.T) { 14 | t.Skip() 15 | } 16 | 17 | func shouldPanic(expect string, f func()) { 18 | defer func() { 19 | r := recover() 20 | if r == nil { 21 | panic("did not panic") 22 | } 23 | if expect != "" { 24 | var s string 25 | switch r := r.(type) { 26 | case string: 27 | s = r 28 | case *ValueError: 29 | s = r.Error() 30 | default: 31 | panic(fmt.Sprintf("panicked with unexpected type %T", r)) 32 | } 33 | if !strings.HasPrefix(s, "reflect") { 34 | panic(`panic string does not start with "reflect": ` + s) 35 | } 36 | if !strings.Contains(s, expect) { 37 | // panic(`panic string does not contain "` + expect + `": ` + s) 38 | } 39 | } 40 | }() 41 | f() 42 | } 43 | -------------------------------------------------------------------------------- /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 | 13 | func TestFowler(t *testing.T) { 14 | t.Skip() 15 | } 16 | -------------------------------------------------------------------------------- /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/go114_runtime.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | // +build go1.14 3 | 4 | package runtime 5 | 6 | import ( 7 | "runtime/internal/sys" 8 | "unsafe" 9 | 10 | "github.com/gopherjs/gopherjs/js" 11 | ) 12 | 13 | const ( 14 | // Constants for multiplication: four random odd 32-bit numbers. 15 | m1 = 3168982561 16 | m2 = 3339683297 17 | m3 = 832293441 18 | m4 = 2336365089 19 | ) 20 | 21 | func memhash(p unsafe.Pointer, seed, s uintptr) uintptr { 22 | h := uint32(seed + s*hashkey[0]) 23 | tail: 24 | switch { 25 | case s == 0: 26 | case s < 4: 27 | data := js.InternalObject(p).Interface().([]byte) 28 | h ^= uint32(data[0]) 29 | h ^= uint32(data[1]) << 8 30 | h ^= uint32(data[2]) << 16 31 | h = rotl_15(h*m1) * m2 32 | case s == 4: 33 | h ^= readUnaligned32(p) 34 | h = rotl_15(h*m1) * m2 35 | case s <= 8: 36 | h ^= readUnaligned32(p) 37 | h = rotl_15(h*m1) * m2 38 | h ^= readUnaligned32(add(p, s-4)) 39 | h = rotl_15(h*m1) * m2 40 | case s <= 16: 41 | h ^= readUnaligned32(p) 42 | h = rotl_15(h*m1) * m2 43 | h ^= readUnaligned32(add(p, 4)) 44 | h = rotl_15(h*m1) * m2 45 | h ^= readUnaligned32(add(p, s-8)) 46 | h = rotl_15(h*m1) * m2 47 | h ^= readUnaligned32(add(p, s-4)) 48 | h = rotl_15(h*m1) * m2 49 | default: 50 | v1 := h 51 | v2 := uint32(seed * hashkey[1]) 52 | v3 := uint32(seed * hashkey[2]) 53 | v4 := uint32(seed * hashkey[3]) 54 | for s >= 16 { 55 | v1 ^= readUnaligned32(p) 56 | v1 = rotl_15(v1*m1) * m2 57 | p = add(p, 4) 58 | v2 ^= readUnaligned32(p) 59 | v2 = rotl_15(v2*m2) * m3 60 | p = add(p, 4) 61 | v3 ^= readUnaligned32(p) 62 | v3 = rotl_15(v3*m3) * m4 63 | p = add(p, 4) 64 | v4 ^= readUnaligned32(p) 65 | v4 = rotl_15(v4*m4) * m1 66 | p = add(p, 4) 67 | s -= 16 68 | } 69 | h = v1 ^ v2 ^ v3 ^ v4 70 | goto tail 71 | } 72 | h ^= h >> 17 73 | h *= m3 74 | h ^= h >> 13 75 | h *= m4 76 | h ^= h >> 16 77 | return uintptr(h) 78 | } 79 | 80 | // Note: These routines perform the read with a native endianness. 81 | func readUnaligned32(p unsafe.Pointer) uint32 { 82 | q := (*[4]byte)(p) 83 | if sys.BigEndian { 84 | return uint32(q[3]) | uint32(q[2])<<8 | uint32(q[1])<<16 | uint32(q[0])<<24 85 | } 86 | return uint32(q[0]) | uint32(q[1])<<8 | uint32(q[2])<<16 | uint32(q[3])<<24 87 | } 88 | 89 | // Note: in order to get the compiler to issue rotl instructions, we 90 | // need to constant fold the shift amount by hand. 91 | // TODO: convince the compiler to issue rotl instructions after inlining. 92 | func rotl_15(x uint32) uint32 { 93 | return (x << 15) | (x >> (32 - 15)) 94 | } 95 | 96 | // Should be a built-in for unsafe.Pointer? 97 | //go:nosplit 98 | func add(p unsafe.Pointer, x uintptr) unsafe.Pointer { 99 | data := js.InternalObject(p).Interface().([]byte) 100 | return unsafe.Pointer(js.InternalObject(data[x:]).Unsafe()) 101 | } 102 | 103 | // used in hash{32,64}.go to seed the hash function 104 | var hashkey [4]uintptr 105 | 106 | var memhash_has_init bool 107 | 108 | func memhash_init() { 109 | if memhash_has_init { 110 | return 111 | } 112 | memhash_has_init = true 113 | var hash [16]byte 114 | getRandomData(hash[:]) 115 | obj := js.NewArrayBuffer(hash[:]) 116 | v := js.Global.Get("Uint32Array").New(obj) 117 | for i := 0; i < v.Length(); i++ { 118 | hashkey[i] = v.Index(i).Unsafe() 119 | } 120 | hashkey[0] |= 1 // make sure these numbers are odd 121 | hashkey[1] |= 1 122 | hashkey[2] |= 1 123 | hashkey[3] |= 1 124 | } 125 | 126 | //go:nosplit 127 | func getRandomData(r []byte) { 128 | extendRandom(r, 0) 129 | } 130 | 131 | // extendRandom extends the random numbers in r[:n] to the whole slice r. 132 | // Treats n<0 as n==0. 133 | func extendRandom(r []byte, n int) { 134 | if n < 0 { 135 | n = 0 136 | } 137 | for n < len(r) { 138 | // Extend random bits using hash function & time seed 139 | w := n 140 | if w > 16 { 141 | w = 16 142 | } 143 | seed := js.Global.Get("Date").New().Call("getTime").Unsafe() 144 | h := memhash(unsafe.Pointer(&r[n-w]), seed, uintptr(w)) 145 | for i := 0; i < sys.PtrSize && n < len(r); i++ { 146 | r[n] = byte(h) 147 | n++ 148 | h >>= 8 149 | } 150 | } 151 | } 152 | 153 | func nanotime() int64 { 154 | return js.Global.Get("Date").New().Call("getTime").Int64() * 1e6 155 | } 156 | -------------------------------------------------------------------------------- /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 | "unsafe" 8 | 9 | "github.com/gopherjs/gopherjs/js" 10 | ) 11 | 12 | const GOOS = sys.GOOS 13 | const GOARCH = "js" 14 | const Compiler = "gopherjs" 15 | 16 | type eface struct { 17 | _type *_type 18 | data unsafe.Pointer 19 | } 20 | 21 | type _type struct { 22 | str string 23 | kind uint8 24 | } 25 | 26 | func (t *_type) string() string { 27 | return t.str 28 | } 29 | 30 | func (t *_type) pkgpath() string { 31 | return "" 32 | } 33 | 34 | // An errorString represents a runtime error described by a single string. 35 | type errorString string 36 | 37 | func (e errorString) RuntimeError() {} 38 | 39 | func (e errorString) Error() string { 40 | return "runtime error: " + string(e) 41 | } 42 | 43 | func init() { 44 | jsPkg := js.Global.Get("$packages").Get("github.com/gopherjs/gopherjs/js") 45 | js.Global.Set("$jsObjectPtr", jsPkg.Get("Object").Get("ptr")) 46 | js.Global.Set("$jsErrorPtr", jsPkg.Get("Error").Get("ptr")) 47 | js.Global.Set("$throwRuntimeError", js.InternalObject(throw)) 48 | // avoid dead code elimination 49 | var e error 50 | e = &TypeAssertionError{} 51 | _ = e 52 | } 53 | 54 | func GOROOT() string { 55 | process := js.Global.Get("process") 56 | if process == js.Undefined { 57 | return "/" 58 | } 59 | goroot := process.Get("env").Get("GOROOT") 60 | if goroot != js.Undefined { 61 | return goroot.String() 62 | } 63 | // sys.DefaultGoroot is now gone, can't use it as fallback anymore. 64 | // TODO: See if a better solution is needed. 65 | return "/usr/local/go" 66 | } 67 | 68 | func Breakpoint() { 69 | js.Debugger() 70 | } 71 | 72 | func Caller(skip int) (pc uintptr, file string, line int, ok bool) { 73 | info := js.Global.Get("Error").New().Get("stack").Call("split", "\n").Index(skip + 2) 74 | if info == js.Undefined { 75 | return 0, "", 0, false 76 | } 77 | parts := info.Call("substring", info.Call("indexOf", "(").Int()+1, info.Call("indexOf", ")").Int()).Call("split", ":") 78 | return 0, parts.Index(0).String(), parts.Index(1).Int(), true 79 | } 80 | 81 | func Callers(skip int, pc []uintptr) int { 82 | return 0 83 | } 84 | 85 | // CallersFrames is not implemented for GOARCH=js. 86 | // TODO: Implement if possible. 87 | func CallersFrames(callers []uintptr) *Frames { return &Frames{} } 88 | 89 | type Frames struct{} 90 | 91 | func (ci *Frames) Next() (frame Frame, more bool) { return } 92 | 93 | type Frame struct { 94 | PC uintptr 95 | Func *Func 96 | Function string 97 | File string 98 | Line int 99 | Entry uintptr 100 | } 101 | 102 | func GC() { 103 | } 104 | 105 | func Goexit() { 106 | js.Global.Get("$curGoroutine").Set("exit", true) 107 | js.Global.Call("$throw", nil) 108 | } 109 | 110 | func GOMAXPROCS(n int) int { 111 | return 1 112 | } 113 | 114 | func Gosched() { 115 | c := make(chan struct{}) 116 | js.Global.Call("$setTimeout", js.InternalObject(func() { close(c) }), 0) 117 | <-c 118 | } 119 | 120 | func NumCPU() int { 121 | return 1 122 | } 123 | 124 | func NumGoroutine() int { 125 | return js.Global.Get("$totalGoroutines").Int() 126 | } 127 | 128 | type MemStats struct { 129 | // General statistics. 130 | Alloc uint64 // bytes allocated and still in use 131 | TotalAlloc uint64 // bytes allocated (even if freed) 132 | Sys uint64 // bytes obtained from system (sum of XxxSys below) 133 | Lookups uint64 // number of pointer lookups 134 | Mallocs uint64 // number of mallocs 135 | Frees uint64 // number of frees 136 | 137 | // Main allocation heap statistics. 138 | HeapAlloc uint64 // bytes allocated and still in use 139 | HeapSys uint64 // bytes obtained from system 140 | HeapIdle uint64 // bytes in idle spans 141 | HeapInuse uint64 // bytes in non-idle span 142 | HeapReleased uint64 // bytes released to the OS 143 | HeapObjects uint64 // total number of allocated objects 144 | 145 | // Low-level fixed-size structure allocator statistics. 146 | // Inuse is bytes used now. 147 | // Sys is bytes obtained from system. 148 | StackInuse uint64 // bytes used by stack allocator 149 | StackSys uint64 150 | MSpanInuse uint64 // mspan structures 151 | MSpanSys uint64 152 | MCacheInuse uint64 // mcache structures 153 | MCacheSys uint64 154 | BuckHashSys uint64 // profiling bucket hash table 155 | GCSys uint64 // GC metadata 156 | OtherSys uint64 // other system allocations 157 | 158 | // Garbage collector statistics. 159 | NextGC uint64 // next collection will happen when HeapAlloc ≥ this amount 160 | LastGC uint64 // end time of last collection (nanoseconds since 1970) 161 | PauseTotalNs uint64 162 | PauseNs [256]uint64 // circular buffer of recent GC pause durations, most recent at [(NumGC+255)%256] 163 | PauseEnd [256]uint64 // circular buffer of recent GC pause end times 164 | NumGC uint32 165 | GCCPUFraction float64 // fraction of CPU time used by GC 166 | EnableGC bool 167 | DebugGC bool 168 | 169 | // Per-size allocation statistics. 170 | // 61 is NumSizeClasses in the C code. 171 | BySize [61]struct { 172 | Size uint32 173 | Mallocs uint64 174 | Frees uint64 175 | } 176 | } 177 | 178 | func ReadMemStats(m *MemStats) { 179 | } 180 | 181 | func SetFinalizer(x, f interface{}) { 182 | } 183 | 184 | type Func struct { 185 | opaque struct{} // unexported field to disallow conversions 186 | } 187 | 188 | func (_ *Func) Entry() uintptr { return 0 } 189 | func (_ *Func) FileLine(pc uintptr) (file string, line int) { return "", 0 } 190 | func (_ *Func) Name() string { return "" } 191 | 192 | func FuncForPC(pc uintptr) *Func { 193 | return nil 194 | } 195 | 196 | var MemProfileRate int = 512 * 1024 197 | 198 | func SetBlockProfileRate(rate int) { 199 | } 200 | 201 | func SetMutexProfileFraction(rate int) int { 202 | // TODO: Investigate this. If it's possible to implement, consider doing so, otherwise remove this comment. 203 | return 0 204 | } 205 | 206 | func Stack(buf []byte, all bool) int { 207 | s := js.Global.Get("Error").New().Get("stack") 208 | if s == js.Undefined { 209 | return 0 210 | } 211 | return copy(buf, s.Call("substr", s.Call("indexOf", "\n").Int()+1).String()) 212 | } 213 | 214 | func LockOSThread() {} 215 | 216 | func UnlockOSThread() {} 217 | 218 | func Version() string { 219 | return sys.TheVersion 220 | } 221 | 222 | func StartTrace() error { return nil } 223 | func StopTrace() {} 224 | func ReadTrace() []byte 225 | 226 | // We fake a cgo environment to catch errors. Therefor we have to implement this and always return 0 227 | func NumCgoCall() int64 { 228 | return 0 229 | } 230 | 231 | func efaceOf(ep *interface{}) *eface { 232 | panic("efaceOf: not supported") 233 | } 234 | 235 | func KeepAlive(interface{}) {} 236 | 237 | func throw(s string) { 238 | panic(errorString(s)) 239 | } 240 | 241 | // These are used by panicwrap. Not implemented for GOARCH=js. 242 | // TODO: Implement if possible. 243 | func getcallerpc() uintptr { return 0 } 244 | func findfunc(pc uintptr) funcInfo { return funcInfo{} } 245 | func funcname(f funcInfo) string { return "" } 246 | 247 | type funcInfo struct{} 248 | 249 | func rand32() uint32 { 250 | return uint32(js.Global.Get("Math").Call("random").Float() * (1<<32 - 1)) 251 | } 252 | 253 | var ( 254 | fastrand0 uint32 255 | fastrand1 uint32 256 | ) 257 | 258 | func init() { 259 | fastrand0 = rand32() 260 | fastrand1 = rand32() 261 | } 262 | 263 | func fastrand() uint32 { 264 | // Implement xorshift64+: 2 32-bit xorshift sequences added together. 265 | // Shift triplet [17,7,16] was calculated as indicated in Marsaglia's 266 | // Xorshift paper: https://www.jstatsoft.org/article/view/v008i14/xorshift.pdf 267 | // This generator passes the SmallCrush suite, part of TestU01 framework: 268 | // http://simul.iro.umontreal.ca/testu01/tu01.html 269 | s1, s0 := fastrand0, fastrand1 270 | s1 ^= s1 << 17 271 | s1 = s1 ^ s0 ^ s1>>7 ^ s0>>16 272 | fastrand0, fastrand1 = s0, s1 273 | return s0 + s1 274 | } 275 | -------------------------------------------------------------------------------- /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 | 11 | func shouldPanic(t *testing.T, name string, f func()) { 12 | defer func() { 13 | if recover() == nil { 14 | t.Errorf("%s did not panic", name) 15 | } 16 | }() 17 | f() 18 | } 19 | -------------------------------------------------------------------------------- /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/go113_pool.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | // +build go1.13 3 | 4 | package sync 5 | 6 | import "unsafe" 7 | 8 | type Pool struct { 9 | local unsafe.Pointer 10 | localSize uintptr 11 | 12 | victim unsafe.Pointer 13 | victimSize uintptr 14 | 15 | store []interface{} 16 | New func() interface{} 17 | } 18 | 19 | func (p *Pool) Get() interface{} { 20 | if len(p.store) == 0 { 21 | if p.New != nil { 22 | return p.New() 23 | } 24 | return nil 25 | } 26 | x := p.store[len(p.store)-1] 27 | p.store = p.store[:len(p.store)-1] 28 | return x 29 | } 30 | 31 | func (p *Pool) Put(x interface{}) { 32 | if x == nil { 33 | return 34 | } 35 | p.store = append(p.store, x) 36 | } 37 | 38 | func runtime_registerPoolCleanup(cleanup func()) { 39 | } 40 | -------------------------------------------------------------------------------- /compiler/natives/src/sync/go113_sync.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | // +build go1.13 3 | 4 | package sync 5 | 6 | import "github.com/gopherjs/gopherjs/js" 7 | 8 | var semWaiters = make(map[*uint32][]chan bool) 9 | 10 | // semAwoken tracks the number of waiters awoken by runtime_Semrelease (`ch <- true`) 11 | // that have not yet acquired the semaphore (`<-ch` in runtime_SemacquireMutex). 12 | // 13 | // This prevents a new call to runtime_SemacquireMutex to wrongly acquire the semaphore 14 | // in between (because runtime_Semrelease has already incremented the semaphore while 15 | // all the pending calls to runtime_SemacquireMutex have not yet received from the channel 16 | // and thus decremented the semaphore). 17 | // 18 | // See https://github.com/gopherjs/gopherjs/issues/736. 19 | var semAwoken = make(map[*uint32]uint32) 20 | 21 | func runtime_Semacquire(s *uint32) { 22 | runtime_SemacquireMutex(s, false, 0) 23 | } 24 | 25 | // SemacquireMutex is like Semacquire, but for profiling contended Mutexes. 26 | // Mutex profiling is not supported, so just use the same implementation as runtime_Semacquire. 27 | // TODO: Investigate this. If it's possible to implement, consider doing so, otherwise remove this comment. 28 | func runtime_SemacquireMutex(s *uint32, lifo bool, skipframes int) { 29 | // TODO: Use skipframes if needed/possible. 30 | if (*s - semAwoken[s]) == 0 { 31 | ch := make(chan bool) 32 | if lifo { 33 | semWaiters[s] = append([]chan bool{ch}, semWaiters[s]...) 34 | } else { 35 | semWaiters[s] = append(semWaiters[s], ch) 36 | } 37 | <-ch 38 | semAwoken[s] -= 1 39 | if semAwoken[s] == 0 { 40 | delete(semAwoken, s) 41 | } 42 | } 43 | *s-- 44 | } 45 | 46 | func runtime_Semrelease(s *uint32, handoff bool, skipframes int) { 47 | // TODO: Use handoff, skipframes if needed/possible. 48 | *s++ 49 | 50 | w := semWaiters[s] 51 | if len(w) == 0 { 52 | return 53 | } 54 | 55 | ch := w[0] 56 | w = w[1:] 57 | semWaiters[s] = w 58 | if len(w) == 0 { 59 | delete(semWaiters, s) 60 | } 61 | 62 | semAwoken[s] += 1 63 | 64 | ch <- true 65 | } 66 | 67 | func runtime_notifyListCheck(size uintptr) {} 68 | 69 | func runtime_canSpin(i int) bool { 70 | return false 71 | } 72 | 73 | // Copy of time.runtimeNano. 74 | func runtime_nanotime() int64 { 75 | const millisecond = 1000000 76 | return js.Global.Get("Date").New().Call("getTime").Int64() * millisecond 77 | } 78 | 79 | // Implemented in runtime. 80 | func throw(s string) { 81 | js.Global.Call("$throwRuntimeError", s) 82 | } 83 | -------------------------------------------------------------------------------- /compiler/natives/src/sync/pool.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | // +build !go1.13 3 | 4 | package sync 5 | 6 | import "unsafe" 7 | 8 | type Pool struct { 9 | local unsafe.Pointer 10 | localSize uintptr 11 | 12 | store []interface{} 13 | New func() interface{} 14 | } 15 | 16 | func (p *Pool) Get() interface{} { 17 | if len(p.store) == 0 { 18 | if p.New != nil { 19 | return p.New() 20 | } 21 | return nil 22 | } 23 | x := p.store[len(p.store)-1] 24 | p.store = p.store[:len(p.store)-1] 25 | return x 26 | } 27 | 28 | func (p *Pool) Put(x interface{}) { 29 | if x == nil { 30 | return 31 | } 32 | p.store = append(p.store, x) 33 | } 34 | 35 | func runtime_registerPoolCleanup(cleanup func()) { 36 | } 37 | -------------------------------------------------------------------------------- /compiler/natives/src/sync/sync.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | // +build !go1.13 3 | 4 | package sync 5 | 6 | import "github.com/gopherjs/gopherjs/js" 7 | 8 | var semWaiters = make(map[*uint32][]chan bool) 9 | 10 | // semAwoken tracks the number of waiters awoken by runtime_Semrelease (`ch <- true`) 11 | // that have not yet acquired the semaphore (`<-ch` in runtime_SemacquireMutex). 12 | // 13 | // This prevents a new call to runtime_SemacquireMutex to wrongly acquire the semaphore 14 | // in between (because runtime_Semrelease has already incremented the semaphore while 15 | // all the pending calls to runtime_SemacquireMutex have not yet received from the channel 16 | // and thus decremented the semaphore). 17 | // 18 | // See https://github.com/gopherjs/gopherjs/issues/736. 19 | var semAwoken = make(map[*uint32]uint32) 20 | 21 | func runtime_Semacquire(s *uint32) { 22 | runtime_SemacquireMutex(s, false) 23 | } 24 | 25 | // SemacquireMutex is like Semacquire, but for profiling contended Mutexes. 26 | // Mutex profiling is not supported, so just use the same implementation as runtime_Semacquire. 27 | // TODO: Investigate this. If it's possible to implement, consider doing so, otherwise remove this comment. 28 | func runtime_SemacquireMutex(s *uint32, lifo bool) { 29 | if (*s - semAwoken[s]) == 0 { 30 | ch := make(chan bool) 31 | if lifo { 32 | semWaiters[s] = append([]chan bool{ch}, semWaiters[s]...) 33 | } else { 34 | semWaiters[s] = append(semWaiters[s], ch) 35 | } 36 | <-ch 37 | semAwoken[s] -= 1 38 | if semAwoken[s] == 0 { 39 | delete(semAwoken, s) 40 | } 41 | } 42 | *s-- 43 | } 44 | 45 | func runtime_Semrelease(s *uint32, handoff bool) { 46 | // TODO: Use handoff if needed/possible. 47 | *s++ 48 | 49 | w := semWaiters[s] 50 | if len(w) == 0 { 51 | return 52 | } 53 | 54 | ch := w[0] 55 | w = w[1:] 56 | semWaiters[s] = w 57 | if len(w) == 0 { 58 | delete(semWaiters, s) 59 | } 60 | 61 | semAwoken[s] += 1 62 | 63 | ch <- true 64 | } 65 | 66 | func runtime_notifyListCheck(size uintptr) {} 67 | 68 | func runtime_canSpin(i int) bool { 69 | return false 70 | } 71 | 72 | // Copy of time.runtimeNano. 73 | func runtime_nanotime() int64 { 74 | const millisecond = 1000000 75 | return js.Global.Get("Date").New().Call("getTime").Int64() * millisecond 76 | } 77 | 78 | // Implemented in runtime. 79 | func throw(s string) { 80 | js.Global.Call("$throwRuntimeError", s) 81 | } 82 | -------------------------------------------------------------------------------- /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 | 25 | func TestPoolDequeue(t *testing.T) { 26 | t.Skip() 27 | } 28 | 29 | func TestPoolChain(t *testing.T) { 30 | t.Skip() 31 | } 32 | 33 | func TestIssue40999(t *testing.T) { 34 | t.Skip() 35 | } 36 | -------------------------------------------------------------------------------- /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/go116_syscall_darwin.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | // +build go1.16 3 | 4 | package syscall 5 | 6 | func libc_getattrlist_trampoline() {} 7 | -------------------------------------------------------------------------------- /compiler/natives/src/syscall/js/go112_js.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | // +build !go1.13 3 | 4 | package js 5 | 6 | func (v Value) String() string { 7 | return v.internal().String() 8 | } 9 | -------------------------------------------------------------------------------- /compiler/natives/src/syscall/js/go113_js.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | // +build go1.13 3 | 4 | package js 5 | 6 | func (v Value) String() string { 7 | switch v.Type() { 8 | case TypeString: 9 | return v.internal().String() 10 | case TypeUndefined: 11 | return "" 12 | case TypeNull: 13 | return "" 14 | case TypeBoolean: 15 | return "" 16 | case TypeNumber: 17 | return "" 18 | case TypeSymbol: 19 | return "" 20 | case TypeObject: 21 | return "" 22 | case TypeFunction: 23 | return "" 24 | default: 25 | panic("bad type") 26 | } 27 | } 28 | 29 | // CopyBytesToGo copies bytes from the Uint8Array src to dst. 30 | // It returns the number of bytes copied, which will be the minimum of the lengths of src and dst. 31 | // CopyBytesToGo panics if src is not an Uint8Array. 32 | func CopyBytesToGo(dst []byte, src Value) int { 33 | return copy(dst, src.internal().Interface().([]byte)) 34 | } 35 | 36 | // func CopyBytesToGo(dst []byte, src Value) int { 37 | // s := make([]byte, src.Get("byteLength").Int()) 38 | // a := TypedArrayOf(s) 39 | // a.Call("set", src) 40 | // a.Release() 41 | // return copy(dst, s) 42 | // } 43 | 44 | // CopyBytesToJS copies bytes from src to the Uint8Array dst. 45 | // It returns the number of bytes copied, which will be the minimum of the lengths of src and dst. 46 | // CopyBytesToJS panics if dst is not an Uint8Array. 47 | func CopyBytesToJS(dst Value, src []byte) int { 48 | return copy(dst.internal().Interface().([]byte), src) 49 | } 50 | 51 | // func CopyBytesToJS(dst Value, src []byte) int { 52 | // n := dst.Get("byteLength").Int() 53 | // if n > len(src) { 54 | // n = len(src) 55 | // } 56 | // a := TypedArrayOf(src[:n]) 57 | // dst.Call("set", a) 58 | // a.Release() 59 | // return n 60 | // } 61 | -------------------------------------------------------------------------------- /compiler/natives/src/syscall/js/go114_js.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | // +build go1.14 3 | 4 | package js 5 | 6 | import ( 7 | "github.com/gopherjs/gopherjs/js" 8 | ) 9 | 10 | func (v Value) IsNull() bool { 11 | return v.Type() == TypeNull 12 | } 13 | 14 | func (v Value) IsUndefined() bool { 15 | return !v.inited 16 | } 17 | 18 | func (v Value) IsNaN() bool { 19 | return js.Global.Call("isNaN", v.internal()).Bool() 20 | } 21 | 22 | func (v Value) Equal(w Value) bool { 23 | //return v.internal() == w.internal() && !v.IsNaN() 24 | if v.Type() != w.Type() { 25 | return false 26 | } 27 | switch v.Type() { 28 | case TypeString: 29 | return v.internal().String() == w.internal().String() 30 | case TypeUndefined: 31 | return true 32 | case TypeNull: 33 | return true 34 | case TypeBoolean: 35 | return v.internal().Bool() == w.internal().Bool() 36 | case TypeNumber: 37 | return v.internal().Float() == w.internal().Float() 38 | case TypeSymbol: 39 | return v.internal() == w.internal() 40 | case TypeObject: 41 | return v.internal() == w.internal() 42 | case TypeFunction: 43 | return v.internal() == w.internal() 44 | default: 45 | panic("bad type") 46 | } 47 | } 48 | 49 | func (v Value) Delete(p string) { 50 | if vType := v.Type(); vType != TypeObject { 51 | panic(&ValueError{"Value.Delete", vType}) 52 | } 53 | v.internal().Delete(p) 54 | } 55 | -------------------------------------------------------------------------------- /compiler/natives/src/syscall/js/js.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package js 4 | 5 | import ( 6 | "reflect" 7 | "unsafe" 8 | 9 | "github.com/gopherjs/gopherjs/js" 10 | ) 11 | 12 | type Type int 13 | 14 | const ( 15 | TypeUndefined Type = iota 16 | TypeNull 17 | TypeBoolean 18 | TypeNumber 19 | TypeString 20 | TypeSymbol 21 | TypeObject 22 | TypeFunction 23 | ) 24 | 25 | func (t Type) String() string { 26 | switch t { 27 | case TypeUndefined: 28 | return "undefined" 29 | case TypeNull: 30 | return "null" 31 | case TypeBoolean: 32 | return "boolean" 33 | case TypeNumber: 34 | return "number" 35 | case TypeString: 36 | return "string" 37 | case TypeSymbol: 38 | return "symbol" 39 | case TypeObject: 40 | return "object" 41 | case TypeFunction: 42 | return "function" 43 | default: 44 | panic("bad type") 45 | } 46 | } 47 | 48 | func Global() Value { 49 | return objectToValue(js.Global) 50 | } 51 | 52 | func Null() Value { 53 | return objectToValue(nil) 54 | } 55 | 56 | func Undefined() Value { 57 | return objectToValue(js.Undefined) 58 | } 59 | 60 | type Func struct { 61 | Value 62 | } 63 | 64 | func (f Func) Release() { 65 | f.Value = Null() 66 | } 67 | 68 | func FuncOf(fn func(this Value, args []Value) interface{}) Func { 69 | return Func{ 70 | Value: objectToValue(js.MakeFunc(func(this *js.Object, args []*js.Object) interface{} { 71 | vargs := make([]Value, len(args)) 72 | for i, a := range args { 73 | vargs[i] = objectToValue(a) 74 | } 75 | return fn(objectToValue(this), vargs) 76 | })), 77 | } 78 | } 79 | 80 | type Error struct { 81 | Value 82 | } 83 | 84 | func (e Error) Error() string { 85 | return "JavaScript error: " + e.Get("message").String() 86 | } 87 | 88 | type Value struct { 89 | v *js.Object 90 | 91 | // inited represents whether Value is non-zero value. true represents the value is not 'undefined'. 92 | inited bool 93 | } 94 | 95 | func objectToValue(obj *js.Object) Value { 96 | if obj == js.Undefined { 97 | return Value{} 98 | } 99 | return Value{obj, true} 100 | } 101 | 102 | var ( 103 | id *js.Object 104 | instanceOf *js.Object 105 | getValueType *js.Object 106 | ) 107 | 108 | func init() { 109 | if js.Global != nil { 110 | id = js.Global.Call("eval", "(function(x) { return x; })") 111 | instanceOf = js.Global.Call("eval", "(function(x, y) { return x instanceof y; })") 112 | getValueType = js.Global.Call("eval", `(function(x) { 113 | if (typeof(x) === "undefined") { 114 | return 0; // TypeUndefined 115 | } 116 | if (x === null) { 117 | return 1; // TypeNull 118 | } 119 | if (typeof(x) === "boolean") { 120 | return 2; // TypeBoolean 121 | } 122 | if (typeof(x) === "number") { 123 | return 3; // TypeNumber 124 | } 125 | if (typeof(x) === "string") { 126 | return 4; // TypeString 127 | } 128 | if (typeof(x) === "symbol") { 129 | return 5; // TypeSymbol 130 | } 131 | if (typeof(x) === "function") { 132 | return 7; // TypeFunction 133 | } 134 | return 6; // TypeObject 135 | })`) 136 | } 137 | } 138 | 139 | func ValueOf(x interface{}) Value { 140 | switch x := x.(type) { 141 | case Value: 142 | return x 143 | case Func: 144 | return x.Value 145 | case TypedArray: 146 | return x.Value 147 | case nil: 148 | return Null() 149 | case bool, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, unsafe.Pointer, string, map[string]interface{}, []interface{}: 150 | return objectToValue(id.Invoke(x)) 151 | default: 152 | panic(`invalid arg: ` + reflect.TypeOf(x).String()) 153 | } 154 | } 155 | 156 | func (v Value) internal() *js.Object { 157 | if !v.inited { 158 | return js.Undefined 159 | } 160 | return v.v 161 | } 162 | 163 | func (v Value) Bool() bool { 164 | if vType := v.Type(); vType != TypeBoolean { 165 | panic(&ValueError{"Value.Bool", vType}) 166 | } 167 | return v.internal().Bool() 168 | } 169 | 170 | // convertArgs converts arguments into values for GopherJS arguments. 171 | func convertArgs(args ...interface{}) []interface{} { 172 | newArgs := []interface{}{} 173 | for _, arg := range args { 174 | v := ValueOf(arg) 175 | newArgs = append(newArgs, v.internal()) 176 | } 177 | return newArgs 178 | } 179 | 180 | func (v Value) Call(m string, args ...interface{}) Value { 181 | if vType := v.Type(); vType != TypeObject && vType != TypeFunction { 182 | panic(&ValueError{"Value.Call", vType}) 183 | } 184 | if propType := v.Get(m).Type(); propType != TypeFunction { 185 | panic("js: Value.Call: property " + m + " is not a function, got " + propType.String()) 186 | } 187 | return objectToValue(v.internal().Call(m, convertArgs(args...)...)) 188 | } 189 | 190 | func (v Value) Float() float64 { 191 | if vType := v.Type(); vType != TypeNumber { 192 | panic(&ValueError{"Value.Float", vType}) 193 | } 194 | return v.internal().Float() 195 | } 196 | 197 | func (t Type) isObject() bool { 198 | return t == TypeObject || t == TypeFunction 199 | } 200 | 201 | func (v Value) Get(p string) Value { 202 | if vType := v.Type(); !vType.isObject() { 203 | panic(&ValueError{"Value.Get", vType}) 204 | } 205 | return objectToValue(v.internal().Get(p)) 206 | } 207 | 208 | func (v Value) Index(i int) Value { 209 | if vType := v.Type(); !vType.isObject() { 210 | panic(&ValueError{"Value.Index", vType}) 211 | } 212 | return objectToValue(v.internal().Index(i)) 213 | } 214 | 215 | func (v Value) Int() int { 216 | if vType := v.Type(); vType != TypeNumber { 217 | panic(&ValueError{"Value.Int", vType}) 218 | } 219 | return v.internal().Int() 220 | } 221 | 222 | func (v Value) InstanceOf(t Value) bool { 223 | return instanceOf.Invoke(v.internal(), t.internal()).Bool() 224 | } 225 | 226 | func (v Value) Invoke(args ...interface{}) Value { 227 | if vType := v.Type(); vType != TypeFunction { 228 | panic(&ValueError{"Value.Invoke", vType}) 229 | } 230 | return objectToValue(v.internal().Invoke(convertArgs(args...)...)) 231 | } 232 | 233 | func (v Value) JSValue() Value { 234 | return v 235 | } 236 | 237 | func (v Value) Length() int { 238 | return v.internal().Length() 239 | } 240 | 241 | func (v Value) newWrap(args ...interface{}) (obj *js.Object, err error) { 242 | defer func() { 243 | ret := recover() 244 | if r, ok := ret.(*js.Error); ok { 245 | err = r 246 | } 247 | }() 248 | obj = v.internal().New(convertArgs(args...)...) 249 | return 250 | } 251 | 252 | func (v Value) New(args ...interface{}) Value { 253 | obj, err := v.newWrap(args...) 254 | if err != nil { 255 | if vType := v.Type(); vType != TypeFunction { // check here to avoid overhead in success case 256 | panic(&ValueError{"Value.Invoke", vType}) 257 | } 258 | panic(Error{objectToValue(obj)}) 259 | } 260 | return objectToValue(obj) 261 | } 262 | 263 | func (v Value) Set(p string, x interface{}) { 264 | if vType := v.Type(); !vType.isObject() { 265 | panic(&ValueError{"Value.Set", vType}) 266 | } 267 | v.internal().Set(p, convertArgs(x)[0]) 268 | } 269 | 270 | func (v Value) SetIndex(i int, x interface{}) { 271 | if vType := v.Type(); !vType.isObject() { 272 | panic(&ValueError{"Value.SetIndex", vType}) 273 | } 274 | v.internal().SetIndex(i, convertArgs(x)[0]) 275 | } 276 | 277 | // func (v Value) String() string { 278 | // return v.internal().String() 279 | // } 280 | 281 | func (v Value) Truthy() bool { 282 | return v.internal().Bool() 283 | } 284 | 285 | func (v Value) Type() Type { 286 | return Type(getValueType.Invoke(v.internal()).Int()) 287 | } 288 | 289 | type TypedArray struct { 290 | Value 291 | } 292 | 293 | func TypedArrayOf(slice interface{}) TypedArray { 294 | switch slice := slice.(type) { 295 | case []int8, []int16, []int32, []uint8, []uint16, []uint32, []float32, []float64: 296 | return TypedArray{objectToValue(id.Invoke(slice))} 297 | default: 298 | panic("TypedArrayOf: not a supported slice") 299 | } 300 | } 301 | 302 | func (t *TypedArray) Release() { 303 | t.Value = Value{} 304 | } 305 | 306 | type ValueError struct { 307 | Method string 308 | Type Type 309 | } 310 | 311 | func (e *ValueError) Error() string { 312 | return "syscall/js: call of " + e.Method + " on " + e.Type.String() 313 | } 314 | 315 | type Wrapper interface { 316 | JSValue() Value 317 | } 318 | -------------------------------------------------------------------------------- /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_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/go116_helper.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | // +build go1.16 3 | 4 | package testing 5 | 6 | // Helper may be called simultaneously from multiple goroutines. 7 | func (c *common) Helper() { 8 | c.mu.Lock() 9 | defer c.mu.Unlock() 10 | if c.helperPCs == nil { 11 | c.helperPCs = make(map[uintptr]struct{}) 12 | } 13 | c.helperPCs[0] = struct{}{} 14 | c.helperNames = nil // map will be recreated next time it is needed 15 | } 16 | -------------------------------------------------------------------------------- /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/examplefiles_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package template_test 4 | 5 | import ( 6 | "fmt" 7 | ) 8 | 9 | func ExampleTemplate_glob() { 10 | fmt.Print("T0 invokes T1: (T1 invokes T2: (This is T2))") 11 | // Output: 12 | // T0 invokes T1: (T1 invokes T2: (This is T2)) 13 | } 14 | 15 | func ExampleTemplate_helpers() { 16 | fmt.Print(` 17 | Driver 1 calls T1: (T1 invokes T2: (This is T2)) 18 | Driver 2 calls T2: (This is T2)`) 19 | // Output: 20 | // Driver 1 calls T1: (T1 invokes T2: (This is T2)) 21 | // Driver 2 calls T2: (This is T2) 22 | } 23 | 24 | func ExampleTemplate_share() { 25 | fmt.Print(` 26 | T0 (second version) invokes T1: (T1 invokes T2: (T2, version B)) 27 | T0 (first version) invokes T1: (T1 invokes T2: (T2, version A)) 28 | `) 29 | // Output: 30 | // T0 (second version) invokes T1: (T1 invokes T2: (T2, version B)) 31 | // T0 (first version) invokes T1: (T1 invokes T2: (T2, version A)) 32 | } 33 | -------------------------------------------------------------------------------- /compiler/natives/src/text/template/template.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package template 4 | 5 | const maxExecDepth = 3000 6 | -------------------------------------------------------------------------------- /compiler/natives/src/text/template/template_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package template 4 | 5 | import "testing" 6 | 7 | func TestParseGlob(t *testing.T) { 8 | t.Skip() 9 | } 10 | 11 | func TestParseGlobWithData(t *testing.T) { 12 | t.Skip() 13 | } 14 | 15 | func TestParseFilesWithData(t *testing.T) { 16 | t.Skip() 17 | } 18 | 19 | func TestParseFiles(t *testing.T) { 20 | t.Skip() 21 | } 22 | 23 | func ExampleTemplate_glob() { 24 | 25 | } 26 | -------------------------------------------------------------------------------- /compiler/natives/src/time/go114_timer.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | // +build go1.14 3 | 4 | package time 5 | 6 | func resetTimer(r *runtimeTimer, w int64) bool { 7 | active := stopTimer(r) 8 | r.when = w 9 | startTimer(r) 10 | return active 11 | } 12 | -------------------------------------------------------------------------------- /compiler/natives/src/time/go115_timer.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | // +build go1.15 3 | 4 | package time 5 | 6 | import "github.com/gopherjs/gopherjs/js" 7 | 8 | type runtimeTimer struct { 9 | i int32 10 | when int64 11 | period int64 12 | f func(interface{}, uintptr) 13 | arg interface{} 14 | timeout *js.Object 15 | active bool 16 | seq uintptr 17 | } 18 | 19 | func (t *Ticker) Reset(d Duration) { 20 | if t.r.f == nil { 21 | panic("time: Reset called on uninitialized Ticker") 22 | } 23 | stopTimer(&t.r) 24 | c := make(chan Time, 1) 25 | t.C = c 26 | t.r = runtimeTimer{ 27 | when: when(d), 28 | period: int64(d), 29 | f: sendTime, 30 | arg: c, 31 | } 32 | startTimer(&t.r) 33 | } 34 | -------------------------------------------------------------------------------- /compiler/natives/src/time/internal_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package time 4 | 5 | func initTestingZone() { 6 | z, err := loadLocation("America/Los_Angeles", zoneSources) 7 | if err != nil { 8 | panic("cannot load America/Los_Angeles for testing: " + err.Error()) 9 | } 10 | z.name = "Local" 11 | localLoc = *z 12 | } 13 | 14 | func forceZipFileForTesting(zipOnly bool) { 15 | } 16 | -------------------------------------------------------------------------------- /compiler/natives/src/time/time.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package time 4 | 5 | import ( 6 | "github.com/gopherjs/gopherjs/js" 7 | ) 8 | 9 | // Make sure time.Unix func and time.Time struct it returns are always included with this package (despite DCE), 10 | // because they're needed for internalization/externalization of time.Time/Date. See issue https://github.com/gopherjs/gopherjs/issues/279. 11 | func init() { 12 | // avoid dead code elimination 13 | var _ Time = Unix(0, 0) 14 | } 15 | 16 | func runtimeNano() int64 { 17 | return js.Global.Get("Date").New().Call("getTime").Int64() * int64(Millisecond) 18 | } 19 | 20 | func now() (sec int64, nsec int32, mono int64) { 21 | n := runtimeNano() 22 | return n / int64(Second), int32(n % int64(Second)), n 23 | } 24 | 25 | func Sleep(d Duration) { 26 | c := make(chan struct{}) 27 | js.Global.Call("$setTimeout", js.InternalObject(func() { close(c) }), int(d/Millisecond)) 28 | <-c 29 | } 30 | 31 | func startTimer(t *runtimeTimer) { 32 | t.active = true 33 | diff := (t.when - runtimeNano()) / int64(Millisecond) 34 | if diff > 1<<31-1 { // math.MaxInt32 35 | return 36 | } 37 | if diff < 0 { 38 | diff = 0 39 | } 40 | t.timeout = js.Global.Call("$setTimeout", js.InternalObject(func() { 41 | t.active = false 42 | if t.period != 0 { 43 | t.when += t.period 44 | startTimer(t) 45 | } 46 | go t.f(t.arg, 0) 47 | }), diff+1) 48 | } 49 | 50 | func stopTimer(t *runtimeTimer) bool { 51 | js.Global.Call("clearTimeout", t.timeout) 52 | wasActive := t.active 53 | t.active = false 54 | return wasActive 55 | } 56 | 57 | // indexByte is copied from strings package to avoid importing it (since the real time package doesn't). 58 | func indexByte(s string, c byte) int { 59 | return js.InternalObject(s).Call("indexOf", js.Global.Get("String").Call("fromCharCode", c)).Int() 60 | } 61 | -------------------------------------------------------------------------------- /compiler/natives/src/time/time_test.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package time_test 4 | 5 | import ( 6 | "testing" 7 | ) 8 | 9 | func TestSleep(t *testing.T) { 10 | t.Skip("time.Now() is not accurate enough for the test") 11 | } 12 | 13 | func TestBadLocationErrMsg(t *testing.T) { 14 | t.Skip() 15 | } 16 | 17 | func TestLoadLocationFromTZData(t *testing.T) { 18 | t.Skip() 19 | } 20 | 21 | func TestEnvTZUsage(t *testing.T) { 22 | t.Skip() 23 | } 24 | 25 | func TestEmbeddedTZData(t *testing.T) { 26 | t.Skip() 27 | } 28 | -------------------------------------------------------------------------------- /compiler/natives/src/time/timer.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | // +build !go1.15 3 | 4 | package time 5 | 6 | import "github.com/gopherjs/gopherjs/js" 7 | 8 | type runtimeTimer struct { 9 | i int32 10 | when int64 11 | period int64 12 | f func(interface{}, uintptr) 13 | arg interface{} 14 | timeout *js.Object 15 | active bool 16 | req uintptr 17 | } 18 | -------------------------------------------------------------------------------- /compiler/natives/src/time/zoneinfo.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package time 4 | 5 | import ( 6 | "runtime" 7 | 8 | "github.com/gopherjs/gopherjs/js" 9 | ) 10 | 11 | var zoneSources = []string{ 12 | "/usr/share/zoneinfo/", 13 | "/usr/share/lib/zoneinfo/", 14 | "/usr/lib/locale/TZ/", 15 | runtime.GOROOT() + "/lib/time/zoneinfo.zip", 16 | } 17 | 18 | func initLocal() { 19 | localLoc.name = "Local" 20 | 21 | z := zone{} 22 | d := js.Global.Get("Date").New() 23 | offset := d.Call("getTimezoneOffset").Int() * -1 24 | z.offset = offset * 60 25 | // According to https://tc39.github.io/ecma262/#sec-timezoneestring, 26 | // the timezone name from (new Date()).toTimeString() is an implementation-dependent 27 | // result, and in Google Chrome, it gives the fully expanded name rather than 28 | // the abbreviation. 29 | // Hence, we construct the name from the offset. 30 | z.name = "UTC" 31 | if offset < 0 { 32 | z.name += "-" 33 | offset *= -1 34 | } else { 35 | z.name += "+" 36 | } 37 | z.name += itoa(offset / 60) 38 | min := offset % 60 39 | if min != 0 { 40 | z.name += ":" + itoa(min) 41 | } 42 | localLoc.zone = []zone{z} 43 | } 44 | 45 | // itoa is like strconv.Itoa but only works for values of i in range [0,99]. 46 | // It panics if i is out of range. 47 | func itoa(i int) string { 48 | if i < 10 { 49 | return digits[i : i+1] 50 | } 51 | return smallsString[i*2 : i*2+2] 52 | } 53 | 54 | const smallsString = "00010203040506070809" + 55 | "10111213141516171819" + 56 | "20212223242526272829" + 57 | "30313233343536373839" + 58 | "40414243444546474849" + 59 | "50515253545556575859" + 60 | "60616263646566676869" + 61 | "70717273747576777879" + 62 | "80818283848586878889" + 63 | "90919293949596979899" 64 | const digits = "0123456789" 65 | -------------------------------------------------------------------------------- /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/natives/src/vendor/golang.org/x/sys/cpu/cpu.go: -------------------------------------------------------------------------------- 1 | package cpu 2 | 3 | const ( 4 | cacheLineSize = 64 5 | ) 6 | -------------------------------------------------------------------------------- /compiler/prelude/genmin.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 | "github.com/goplusjs/gopherjs/compiler/prelude" 16 | ) 17 | 18 | func main() { 19 | if err := run(); err != nil { 20 | log.Fatalln(err) 21 | } 22 | } 23 | 24 | func run() error { 25 | bpkg, err := build.Import("github.com/goplusjs/gopherjs", "", build.FindOnly) 26 | if err != nil { 27 | return fmt.Errorf("failed to locate path for github.com/gopherjs/gopherjs: %v", err) 28 | } 29 | 30 | preludeDir := filepath.Join(bpkg.Dir, "compiler", "prelude") 31 | 32 | args := []string{ 33 | filepath.Join(bpkg.Dir, "node_modules", ".bin", "uglifyjs"), 34 | "--config-file", 35 | filepath.Join(preludeDir, "uglifyjs_options.json"), 36 | } 37 | 38 | stderr := new(bytes.Buffer) 39 | cmd := exec.Command(args[0], args[1:]...) 40 | cmd.Stdin = strings.NewReader(prelude.Prelude) 41 | cmd.Stderr = stderr 42 | 43 | out, err := cmd.Output() 44 | if err != nil { 45 | return fmt.Errorf("failed to run %v: %v\n%s", strings.Join(args, " "), err, stderr.String()) 46 | } 47 | 48 | fn := "prelude_min.go" 49 | 50 | outStr := fmt.Sprintf(`// Code generated by genmin; DO NOT EDIT. 51 | 52 | package prelude 53 | 54 | // Minified is an uglifyjs-minified version of Prelude. 55 | const Minified = %q 56 | `, out) 57 | 58 | if err := ioutil.WriteFile(fn, []byte(outStr), 0644); err != nil { 59 | return fmt.Errorf("failed to write to %v: %v", fn, err) 60 | } 61 | 62 | return nil 63 | } 64 | -------------------------------------------------------------------------------- /compiler/prelude/numeric.go: -------------------------------------------------------------------------------- 1 | package prelude 2 | 3 | const numeric = ` 4 | var $min = Math.min; 5 | var $mod = function(x, y) { return x % y; }; 6 | var $parseInt = parseInt; 7 | var $parseFloat = function(f) { 8 | if (f !== undefined && f !== null && f.constructor === Number) { 9 | return f; 10 | } 11 | return parseFloat(f); 12 | }; 13 | 14 | var $froundBuf = new Float32Array(1); 15 | var $fround = Math.fround || function(f) { 16 | $froundBuf[0] = f; 17 | return $froundBuf[0]; 18 | }; 19 | 20 | var $imul = Math.imul || function(a, b) { 21 | var ah = (a >>> 16) & 0xffff; 22 | var al = a & 0xffff; 23 | var bh = (b >>> 16) & 0xffff; 24 | var bl = b & 0xffff; 25 | return ((al * bl) + (((ah * bl + al * bh) << 16) >>> 0) >> 0); 26 | }; 27 | 28 | var $floatKey = function(f) { 29 | if (f !== f) { 30 | $idCounter++; 31 | return "NaN$" + $idCounter; 32 | } 33 | return String(f); 34 | }; 35 | 36 | var $flatten64 = function(x) { 37 | return x.$high * 4294967296 + x.$low; 38 | }; 39 | 40 | var $shiftLeft64 = function(x, y) { 41 | if (y === 0) { 42 | return x; 43 | } 44 | if (y < 32) { 45 | return new x.constructor(x.$high << y | x.$low >>> (32 - y), (x.$low << y) >>> 0); 46 | } 47 | if (y < 64) { 48 | return new x.constructor(x.$low << (y - 32), 0); 49 | } 50 | return new x.constructor(0, 0); 51 | }; 52 | 53 | var $shiftRightInt64 = function(x, y) { 54 | if (y === 0) { 55 | return x; 56 | } 57 | if (y < 32) { 58 | return new x.constructor(x.$high >> y, (x.$low >>> y | x.$high << (32 - y)) >>> 0); 59 | } 60 | if (y < 64) { 61 | return new x.constructor(x.$high >> 31, (x.$high >> (y - 32)) >>> 0); 62 | } 63 | if (x.$high < 0) { 64 | return new x.constructor(-1, 4294967295); 65 | } 66 | return new x.constructor(0, 0); 67 | }; 68 | 69 | var $shiftRightUint64 = function(x, y) { 70 | if (y === 0) { 71 | return x; 72 | } 73 | if (y < 32) { 74 | return new x.constructor(x.$high >>> y, (x.$low >>> y | x.$high << (32 - y)) >>> 0); 75 | } 76 | if (y < 64) { 77 | return new x.constructor(0, x.$high >>> (y - 32)); 78 | } 79 | return new x.constructor(0, 0); 80 | }; 81 | 82 | var $mul64 = function(x, y) { 83 | var high = 0, low = 0; 84 | if ((y.$low & 1) !== 0) { 85 | high = x.$high; 86 | low = x.$low; 87 | } 88 | for (var i = 1; i < 32; i++) { 89 | if ((y.$low & 1<>> (32 - i); 91 | low += (x.$low << i) >>> 0; 92 | } 93 | } 94 | for (var i = 0; i < 32; i++) { 95 | if ((y.$high & 1< yHigh) || (xHigh === yHigh && xLow > yLow))) { 135 | yHigh = (yHigh << 1 | yLow >>> 31) >>> 0; 136 | yLow = (yLow << 1) >>> 0; 137 | n++; 138 | } 139 | for (var i = 0; i <= n; i++) { 140 | high = high << 1 | low >>> 31; 141 | low = (low << 1) >>> 0; 142 | if ((xHigh > yHigh) || (xHigh === yHigh && xLow >= yLow)) { 143 | xHigh = xHigh - yHigh; 144 | xLow = xLow - yLow; 145 | if (xLow < 0) { 146 | xHigh--; 147 | xLow += 4294967296; 148 | } 149 | low++; 150 | if (low === 4294967296) { 151 | high++; 152 | low = 0; 153 | } 154 | } 155 | yLow = (yLow >>> 1 | yHigh << (32 - 1)) >>> 0; 156 | yHigh = yHigh >>> 1; 157 | } 158 | 159 | if (returnRemainder) { 160 | return new x.constructor(xHigh * rs, xLow * rs); 161 | } 162 | return new x.constructor(high * s, low * s); 163 | }; 164 | 165 | var $divComplex = function(n, d) { 166 | var ninf = n.$real === Infinity || n.$real === -Infinity || n.$imag === Infinity || n.$imag === -Infinity; 167 | var dinf = d.$real === Infinity || d.$real === -Infinity || d.$imag === Infinity || d.$imag === -Infinity; 168 | var nnan = !ninf && (n.$real !== n.$real || n.$imag !== n.$imag); 169 | var dnan = !dinf && (d.$real !== d.$real || d.$imag !== d.$imag); 170 | if(nnan || dnan) { 171 | return new n.constructor(NaN, NaN); 172 | } 173 | if (ninf && !dinf) { 174 | return new n.constructor(Infinity, Infinity); 175 | } 176 | if (!ninf && dinf) { 177 | return new n.constructor(0, 0); 178 | } 179 | if (d.$real === 0 && d.$imag === 0) { 180 | if (n.$real === 0 && n.$imag === 0) { 181 | return new n.constructor(NaN, NaN); 182 | } 183 | return new n.constructor(Infinity, Infinity); 184 | } 185 | var a = Math.abs(d.$real); 186 | var b = Math.abs(d.$imag); 187 | if (a <= b) { 188 | var ratio = d.$real / d.$imag; 189 | var denom = d.$real * ratio + d.$imag; 190 | return new n.constructor((n.$real * ratio + n.$imag) / denom, (n.$imag * ratio - n.$real) / denom); 191 | } 192 | var ratio = d.$imag / d.$real; 193 | var denom = d.$imag * ratio + d.$real; 194 | return new n.constructor((n.$imag * ratio + n.$real) / denom, (n.$imag - n.$real * ratio) / denom); 195 | }; 196 | ` 197 | -------------------------------------------------------------------------------- /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/vendor/github.com/neelance/astrewrite/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 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. -------------------------------------------------------------------------------- /compiler/vendor/vendor.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "", 3 | "ignore": "test", 4 | "package": [ 5 | { 6 | "checksumSHA1": "CaUaJLLnql96d2JGRgCpYsKomxw=", 7 | "path": "github.com/neelance/astrewrite", 8 | "revision": "99348263ae862cc230986ce88deaddbf7edcc034", 9 | "revisionTime": "2016-05-11T09:36:45Z" 10 | } 11 | ], 12 | "rootPath": "github.com/gopherjs/gopherjs/compiler" 13 | } 14 | -------------------------------------------------------------------------------- /compiler/version.go: -------------------------------------------------------------------------------- 1 | package compiler 2 | 3 | // Version is the GopherJS compiler version string. 4 | const Version = "1.16" 5 | -------------------------------------------------------------------------------- /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 | -- maphash | ✅ yes | 87 | html | ✅ yes | 88 | -- template | ✅ yes | 89 | image | ✅ yes | 90 | -- color | ✅ yes | 91 | -- -- palette | ✅ yes | 92 | -- draw | ✅ yes | 93 | -- gif | ✅ yes | 94 | -- jpeg | ✅ yes | 95 | -- png | ✅ yes | 96 | index | | 97 | -- suffixarray | ✅ yes | 98 | io | ✅ yes | 99 | -- ioutil | ✅ yes | 100 | log | ✅ yes | 101 | -- syslog | ❌ no | 102 | math | ✅ yes | 103 | -- big | ✅ yes | 104 | -- bits | ✅ yes | 105 | -- cmplx | ✅ yes | 106 | -- rand | ✅ yes | 107 | mime | ✅ yes | 108 | -- multipart | ✅ yes | 109 | -- quotedprintable | ✅ yes | 110 | net | ❌ no | 111 | -- http | ☑️ partially | client only, emulated via Fetch/XMLHttpRequest APIs;
node.js requires polyfill 112 | -- -- cgi | ❌ no | 113 | -- -- cookiejar | ✅ yes | 114 | -- -- fcgi | ✅ yes | 115 | -- -- httptest | ☑️ partially | 116 | -- -- httputil | ☑️ partially | 117 | -- -- pprof | ❌ no | 118 | -- mail | ✅ yes | 119 | -- rpc | ☑️ partially | data structures only (no net) 120 | -- -- jsonrpc | ✅ yes | 121 | -- smtp | ☑️ partially | data structures only (no net) 122 | -- textproto | ✅ yes | 123 | -- url | ✅ yes | 124 | os | ☑️ partially | node.js only 125 | -- exec | ☑️ partially | node.js only 126 | -- signal | ☑️ partially | node.js only 127 | -- user | ☑️ partially | node.js only 128 | path | ✅ yes | 129 | -- filepath | ✅ yes | 130 | plugin | ❌ no | 131 | reflect | ✅ yes | 132 | regexp | ✅ yes | 133 | -- syntax | ✅ yes | 134 | runtime | ☑️ partially | SetMutexProfileFraction, SetFinalizer, ReadMemStats, Callers, CallersFrames unsupported 135 | -- cgo | ❌ no | 136 | -- debug | ❌ no | 137 | -- pprof | ❌ no | 138 | -- race | ❌ no | 139 | -- trace | ❌ no | 140 | sort | ✅ yes | 141 | strconv | ✅ yes | 142 | strings | ✅ yes | 143 | sync | ✅ yes | 144 | -- atomic | ✅ yes | 145 | syscall | ☑️ partially | node.js only 146 | testing | ☑️ partially | AllocsPerRun unsupported 147 | -- iotest | ✅ yes | 148 | -- quick | ✅ yes | 149 | text | | 150 | -- scanner | ✅ yes | 151 | -- tabwriter | ✅ yes | 152 | -- template | ✅ yes | 153 | -- -- parse | ✅ yes | 154 | time | ✅ yes | UTC and Local only (see [issue](https://github.com/gopherjs/gopherjs/issues/64)) 155 | unicode | ✅ yes | 156 | -- utf16 | ✅ yes | 157 | -- utf8 | ✅ yes | 158 | unsafe | ❌ no | 159 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/goplusjs/gopherjs 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/fsnotify/fsnotify v1.4.7 7 | github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 8 | github.com/kisielk/gotool v1.0.0 9 | github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86 10 | github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab 11 | github.com/shurcooL/go v0.0.0-20191216061654-b114cc39af9f 12 | github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 13 | github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 14 | github.com/spf13/cobra v0.0.5 15 | github.com/spf13/pflag v1.0.5 16 | github.com/visualfc/fastmod v1.3.6 17 | github.com/visualfc/goembed v0.2.1 18 | github.com/visualfc/goversion v1.1.0 19 | golang.org/x/crypto v0.0.0-20200208060501-ecb85df21340 20 | golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9 21 | golang.org/x/tools v0.0.0-20200131143746-097c1f2eed26 22 | ) 23 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 2 | github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= 3 | github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= 4 | github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= 5 | github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= 6 | github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= 7 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 8 | github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= 9 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 10 | github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 h1:l5lAOZEym3oK3SQ2HBHWsJUfbNBiTXJDeW2QDxw9AQ0= 11 | github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= 12 | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= 13 | github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= 14 | github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= 15 | github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= 16 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 17 | github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 18 | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 19 | github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 20 | github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86 h1:D6paGObi5Wud7xg83MaEFyjxQB1W5bz5d0IFppr+ymk= 21 | github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= 22 | github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab h1:eFXv9Nu1lGbrNbj619aWwZfVF5HBrm9Plte8aNptuTI= 23 | github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= 24 | github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= 25 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 26 | github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= 27 | github.com/shurcooL/go v0.0.0-20191216061654-b114cc39af9f h1:gvOuVMIvQ0Ca/afBH/YBfp5f2RWb92DbAI5EjwoFLuc= 28 | github.com/shurcooL/go v0.0.0-20191216061654-b114cc39af9f/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= 29 | github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 h1:bUGsEnyNbVPw06Bs80sCeARAlK8lhwqGyi6UT8ymuGk= 30 | github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= 31 | github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 h1:pXY9qYc/MP5zdvqWEUH6SjNiu7VhSjuVFTFiTcphaLU= 32 | github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= 33 | github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= 34 | github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 35 | github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s= 36 | github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= 37 | github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= 38 | github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 39 | github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= 40 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 41 | github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= 42 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 43 | github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= 44 | github.com/visualfc/fastmod v1.3.6 h1:gFvAxk6VoEbk0JF1XP0KznbQl5hYJN9ZYhRYQy3pcKs= 45 | github.com/visualfc/fastmod v1.3.6/go.mod h1:IpOumy9gVomQ72T+yA7gayE3V1FCNlwr6if3mlqnasY= 46 | github.com/visualfc/goembed v0.2.1 h1:UXDvTQOT/Yayy5HhgbVlwzIWkjoDNc7lRKOQva3kzSc= 47 | github.com/visualfc/goembed v0.2.1/go.mod h1:jCVCz/yTJGyslo6Hta+pYxWWBuq9ADCcIVZBTQ0/iVI= 48 | github.com/visualfc/goversion v1.1.0 h1:EN0YQGRkeGoWTPxPNTnbhyNQyas5leKH5U5lL4t8lRE= 49 | github.com/visualfc/goversion v1.1.0/go.mod h1:Gr3s6bW8NTomhheImwAttqno97Mw6pAnFn2dU8/EMa8= 50 | github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= 51 | golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 52 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 53 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 54 | golang.org/x/crypto v0.0.0-20200208060501-ecb85df21340 h1:KOcEaR10tFr7gdJV2GCKw8Os5yED1u1aOqHjOAb6d2Y= 55 | golang.org/x/crypto v0.0.0-20200208060501-ecb85df21340/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 56 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 57 | golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= 58 | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 59 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 60 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 61 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 62 | golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 63 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 64 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 65 | golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9 h1:1/DFK4b7JH8DmkqhUk48onnSfrPzImPoVxuomtbT2nk= 66 | golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 67 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 68 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 69 | golang.org/x/tools v0.0.0-20200131143746-097c1f2eed26 h1:Xm3yOuwULU693JtNquv+un7Gw/4duNW4Ybem7SaAthY= 70 | golang.org/x/tools v0.0.0-20200131143746-097c1f2eed26/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 71 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 72 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA= 73 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 74 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 75 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 76 | -------------------------------------------------------------------------------- /go116_testpkg.go: -------------------------------------------------------------------------------- 1 | // +build go1.16 2 | 3 | package main 4 | 5 | import ( 6 | "go/build" 7 | "go/token" 8 | 9 | gbuild "github.com/goplusjs/gopherjs/build" 10 | ) 11 | 12 | func makeTestPkg(pkg *gbuild.PackageData, xtest bool) *gbuild.PackageData { 13 | if xtest { 14 | return &gbuild.PackageData{ 15 | Package: &build.Package{ 16 | Name: pkg.Name + "_test", 17 | ImportPath: pkg.ImportPath + "_test", 18 | Dir: pkg.Dir, 19 | GoFiles: pkg.XTestGoFiles, 20 | Imports: pkg.XTestImports, 21 | EmbedPatternPos: pkg.XTestEmbedPatternPos, 22 | }, 23 | IsTest: true, 24 | } 25 | } else { 26 | pmap := make(map[string][]token.Position) 27 | for k, v := range pkg.EmbedPatternPos { 28 | pmap[k] = v 29 | } 30 | for k, v := range pkg.TestEmbedPatternPos { 31 | if ov, ok := pmap[k]; ok { 32 | pmap[k] = append(v, ov...) 33 | } else { 34 | pmap[k] = v 35 | } 36 | } 37 | return &gbuild.PackageData{ 38 | Package: &build.Package{ 39 | Name: pkg.Name, 40 | ImportPath: pkg.ImportPath, 41 | Dir: pkg.Dir, 42 | GoFiles: append(pkg.GoFiles, pkg.TestGoFiles...), 43 | Imports: append(pkg.Imports, pkg.TestImports...), 44 | EmbedPatternPos: pmap, 45 | }, 46 | IsTest: true, 47 | JSFiles: pkg.JSFiles, 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /internal/goversion/version.go: -------------------------------------------------------------------------------- 1 | package goversion 2 | 3 | import ( 4 | "go/build" 5 | "strconv" 6 | 7 | "github.com/visualfc/goversion" 8 | ) 9 | 10 | func ReleaseTags() []string { 11 | if installReleaseTags == nil { 12 | return build.Default.ReleaseTags 13 | } 14 | return installReleaseTags 15 | } 16 | 17 | var ( 18 | installReleaseTags []string 19 | ) 20 | 21 | func buildReleaseTags(version int) (tags []string) { 22 | for i := 1; i <= version; i++ { 23 | tags = append(tags, "go1."+strconv.Itoa(i)) 24 | } 25 | return 26 | } 27 | 28 | func init() { 29 | ver, verinfo, ok := goversion.Installed() 30 | if ok && ver.Major == 1 { 31 | installReleaseTags = buildReleaseTags(ver.Minor) 32 | } else { 33 | installReleaseTags = build.Default.ReleaseTags 34 | } 35 | Version = verinfo 36 | } 37 | 38 | var ( 39 | Version string 40 | ) 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.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gopherjs", 3 | "devDependencies": { 4 | "uglify-es": "3.3.9", 5 | "node-gyp": "5.1.1" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /testpkg.go: -------------------------------------------------------------------------------- 1 | // +build !go1.16 2 | 3 | package main 4 | 5 | import ( 6 | "go/build" 7 | 8 | gbuild "github.com/goplusjs/gopherjs/build" 9 | ) 10 | 11 | func makeTestPkg(pkg *gbuild.PackageData, xtest bool) *gbuild.PackageData { 12 | if xtest { 13 | return &gbuild.PackageData{ 14 | Package: &build.Package{ 15 | Name: pkg.Name + "_test", 16 | ImportPath: pkg.ImportPath + "_test", 17 | Dir: pkg.Dir, 18 | GoFiles: pkg.XTestGoFiles, 19 | Imports: pkg.XTestImports, 20 | }, 21 | IsTest: true, 22 | } 23 | } else { 24 | return &gbuild.PackageData{ 25 | Package: &build.Package{ 26 | Name: pkg.Name, 27 | ImportPath: pkg.ImportPath, 28 | Dir: pkg.Dir, 29 | GoFiles: append(pkg.GoFiles, pkg.TestGoFiles...), 30 | Imports: append(pkg.Imports, pkg.TestImports...), 31 | }, 32 | IsTest: true, 33 | JSFiles: pkg.JSFiles, 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /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/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/gopherjsvendored_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Don't run this file directly. It's executed as part of TestGopherJSCanBeVendored. 3 | 4 | set -e 5 | 6 | tmp=$(mktemp -d "${TMPDIR:-/tmp}/gopherjsvendored_test.XXXXXXXXXX") 7 | 8 | cleanup() { 9 | rm -rf "$tmp" 10 | exit 11 | } 12 | 13 | trap cleanup EXIT HUP INT TERM 14 | 15 | # copyGoPackage copies Go package with import path $1 to directory $2. 16 | # The target directory is created if it doesn't exist. 17 | copyGoPackage() { 18 | mkdir -p "$2" 19 | pkgDir=$(go list -f '{{.Dir}}' "$1") 20 | # Copy all files (not directories), other than ones that start with "." or "_". 21 | for f in $(find -H "$pkgDir" -maxdepth 1 -name "[^._]*" -type f); do 22 | cp "$f" "$2" 23 | done 24 | } 25 | 26 | # Make a hello project that will vendor GopherJS. 27 | mkdir -p "$tmp/src/example.org/hello" 28 | echo 'package main 29 | 30 | import "github.com/gopherjs/gopherjs/js" 31 | 32 | func main() { 33 | js.Global.Get("console").Call("log", "hello using js pkg") 34 | }' > "$tmp/src/example.org/hello/main.go" 35 | 36 | # Vendor GopherJS and its dependencies into hello project. 37 | for pkg in $(go list -f '{{if not .Goroot}}{{.ImportPath}}{{end}}' $(go list -f '{{.ImportPath}} {{join .Deps " "}}' github.com/goplusjs/gopherjs)); do 38 | copyGoPackage "$pkg" "$tmp/src/example.org/hello/vendor/$pkg" 39 | done 40 | 41 | # Make $tmp our GOPATH workspace. 42 | export GOPATH="$tmp" 43 | export GO111MODULE=off 44 | # Build the vendored copy of GopherJS. 45 | go install example.org/hello/vendor/github.com/goplusjs/gopherjs 46 | 47 | # Use it to build and run the hello command. 48 | (cd "$GOPATH/src/example.org/hello" && "$GOPATH/bin/gopherjs" run main.go) 49 | -------------------------------------------------------------------------------- /tests/gorepo_test.go: -------------------------------------------------------------------------------- 1 | package tests_test 2 | 3 | import ( 4 | "os" 5 | "os/exec" 6 | "runtime" 7 | "testing" 8 | ) 9 | 10 | // Go repository basic compiler tests, and regression tests for fixed compiler bugs. 11 | func TestGoRepositoryCompilerTests(t *testing.T) { 12 | if runtime.GOARCH == "js" { 13 | t.Skip("test meant to be run using normal Go compiler (needs os/exec)") 14 | } 15 | 16 | args := []string{"go", "run", "run.go", "-summary"} 17 | if testing.Verbose() { 18 | args = append(args, "-v") 19 | } 20 | cmd := exec.Command(args[0], args[1:]...) 21 | cmd.Stdout = os.Stdout 22 | cmd.Stderr = os.Stdout 23 | err := cmd.Run() 24 | if err != nil { 25 | t.Fatal(err) 26 | } 27 | } 28 | 29 | // Test that GopherJS can be vendored into a project, and then used to build Go programs. 30 | // See issue https://github.com/gopherjs/gopherjs/issues/415. 31 | func TestGopherJSCanBeVendored(t *testing.T) { 32 | if runtime.GOARCH == "js" { 33 | t.Skip("test meant to be run using normal Go compiler (needs os/exec)") 34 | } 35 | if runtime.GOOS == "windows" { 36 | t.Skip("todo, skip vendor test on windows") 37 | } 38 | 39 | cmd := exec.Command("sh", "gopherjsvendored_test.sh") 40 | cmd.Stderr = os.Stdout 41 | got, err := cmd.Output() 42 | if err != nil { 43 | t.Fatal(err) 44 | } 45 | if want := "hello using js pkg\n"; string(got) != want { 46 | t.Errorf("unexpected stdout from gopherjsvendored_test.sh:\ngot:\n%s\nwant:\n%s", got, want) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------