Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .std_test_pkg_exclusions
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ runtime/pprof/internal/profile
runtime/race
runtime/trace
syscall
testing
testing/internal/testdeps
testing/iotest
unsafe
2 changes: 1 addition & 1 deletion build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ func parseAndAugment(bctx *build.Context, pkg *build.Package, isTest bool, fileS
}

switch pkg.ImportPath {
case "crypto/rand", "encoding/gob", "encoding/json", "expvar", "go/token", "log", "math/big", "math/rand", "regexp", "testing", "time":
case "crypto/rand", "encoding/gob", "encoding/json", "expvar", "go/token", "log", "math/big", "math/rand", "regexp", "time":
for _, spec := range file.Imports {
path, _ := strconv.Unquote(spec.Path.Value)
if path == "sync" {
Expand Down
8 changes: 8 additions & 0 deletions compiler/natives/src/os/os.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,11 @@ func runtime_beforeExit() {}
func executable() (string, error) {
return "", errors.New("Executable not implemented for GOARCH=js")
}

func fastrand() uint32 {
// TODO(nevkontakte): Upstream this function is actually linked to runtime.os_fastrand()
// via a go:linkname directive, which is currently unsupported by GopherJS.
// For now we just substitute it with JS's Math.random(), but it is likely slower
// than the fastrand.
return uint32(js.Global.Get("Math").Call("random").Float() * (1<<32 - 1))
}
146 changes: 146 additions & 0 deletions compiler/natives/src/os/removeall_noat.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// GopherJS uses "noat" implementation of os.RemoveAll() because our node-syscall
// module can't handle passing a struct in correctly.
// https://github.com/gopherjs/gopherjs/issues/993

// +build js

package os

import (
"io"
"runtime"
"syscall"
)

func removeAll(path string) error {
if path == "" {
// fail silently to retain compatibility with previous behavior
// of RemoveAll. See issue 28830.
return nil
}

// The rmdir system call permits removing "." on Plan 9,
// so we don't permit it to remain consistent with the
// "at" implementation of RemoveAll.
if endsWithDot(path) {
return &PathError{Op: "RemoveAll", Path: path, Err: syscall.EINVAL}
}

// Simple case: if Remove works, we're done.
err := Remove(path)
if err == nil || IsNotExist(err) {
return nil
}

// Otherwise, is this a directory we need to recurse into?
dir, serr := Lstat(path)
if serr != nil {
if serr, ok := serr.(*PathError); ok && (IsNotExist(serr.Err) || serr.Err == syscall.ENOTDIR) {
return nil
}
return serr
}
if !dir.IsDir() {
// Not a directory; return the error from Remove.
return err
}

// Remove contents & return first error.
err = nil
for {
fd, err := Open(path)
if err != nil {
if IsNotExist(err) {
// Already deleted by someone else.
return nil
}
return err
}

const reqSize = 1024
var names []string
var readErr error

for {
numErr := 0
names, readErr = fd.Readdirnames(reqSize)

for _, name := range names {
err1 := RemoveAll(path + string(PathSeparator) + name)
if err == nil {
err = err1
}
if err1 != nil {
numErr++
}
}

// If we can delete any entry, break to start new iteration.
// Otherwise, we discard current names, get next entries and try deleting them.
if numErr != reqSize {
break
}
}

// Removing files from the directory may have caused
// the OS to reshuffle it. Simply calling Readdirnames
// again may skip some entries. The only reliable way
// to avoid this is to close and re-open the
// directory. See issue 20841.
fd.Close()

if readErr == io.EOF {
break
}
// If Readdirnames returned an error, use it.
if err == nil {
err = readErr
}
if len(names) == 0 {
break
}

// We don't want to re-open unnecessarily, so if we
// got fewer than request names from Readdirnames, try
// simply removing the directory now. If that
// succeeds, we are done.
if len(names) < reqSize {
err1 := Remove(path)
if err1 == nil || IsNotExist(err1) {
return nil
}

if err != nil {
// We got some error removing the
// directory contents, and since we
// read fewer names than we requested
// there probably aren't more files to
// remove. Don't loop around to read
// the directory again. We'll probably
// just get the same error.
return err
}
}
}

// Remove directory.
err1 := Remove(path)
if err1 == nil || IsNotExist(err1) {
return nil
}
if runtime.GOOS == "windows" && IsPermission(err1) {
if fs, err := Stat(path); err == nil {
if err = Chmod(path, FileMode(0200|int(fs.Mode()))); err == nil {
err1 = Remove(path)
}
}
}
if err == nil {
err = err1
}
return err
}
9 changes: 9 additions & 0 deletions compiler/natives/src/testing/allocs_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// +build js

package testing_test

import "testing"

func TestAllocsPerRun(t *testing.T) {
t.Skip("runtime.ReadMemStats() is not supported by GopherJS.")
}
11 changes: 11 additions & 0 deletions compiler/natives/src/testing/helper_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// +build js

package testing

func TestTBHelper(t *T) {
t.Skip("t.Helper() is not supported by GopherJS.")
}

func TestTBHelperParallel(t *T) {
t.Skip("t.Helper() is not supported by GopherJS.")
}
21 changes: 21 additions & 0 deletions compiler/natives/src/testing/sub_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// +build js

package testing

func TestBenchmarkReadMemStatsBeforeFirstRun(t *T) {
t.Skip("runtime.ReadMemStats() is not supported by GopherJS.")
}

func TestTRun(t *T) {
// TODO(nevkontakte): This test performs string comparisons expecting to find
// sub_test.go in the output, but GopherJS currently reports caller
// locations as "test.<random_number>" due to minimal caller and source map support.
t.Skip("GopherJS doesn't support source maps sufficiently.")
}

func TestBRun(t *T) {
// TODO(nevkontakte): This test performs string comparisons expecting to find
// sub_test.go in the output, but GopherJS currently reports caller
// locations as "test.<random_number>" due to minimal caller and source map support.
t.Skip("GopherJS doesn't support source maps sufficiently.")
}
6 changes: 5 additions & 1 deletion compiler/natives/src/testing/testing.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ package testing

import "runtime"

// The upstream callerName and frameSkip rely on runtime.Callers,
// The upstream callerName, frameSkip and Helper rely on runtime.Callers,
// and panic if there are zero callers found. However, runtime.Callers
// is not implemented for GopherJS at this time, so we can't use
// that implementation. Use these stubs instead.
Expand All @@ -24,3 +24,7 @@ func (*common) frameSkip(skip int) runtime.Frame {
Line: line,
}
}

func (c *common) Helper() {
// Not supported by GopherJS.
}