Skip to content
Open
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
26 changes: 24 additions & 2 deletions loader/goroot.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"encoding/hex"
"encoding/json"
"errors"
"go/build"
"io"
"io/fs"
"os"
Expand Down Expand Up @@ -48,7 +49,7 @@ func GetCachedGoroot(config *compileopts.Config) (string, error) {
overrides := pathsToOverride(config.GoMinorVersion, needsSyscallPackage(config.BuildTags()))

// Resolve the merge links within the goroot.
merge, err := listGorootMergeLinks(goroot, tinygoroot, overrides)
merge, err := listGorootMergeLinks(goroot, tinygoroot, overrides, config)
if err != nil {
return "", err
}
Expand Down Expand Up @@ -143,10 +144,22 @@ func GetCachedGoroot(config *compileopts.Config) (string, error) {
}

// listGorootMergeLinks searches goroot and tinygoroot for all symlinks that must be created within the merged goroot.
func listGorootMergeLinks(goroot, tinygoroot string, overrides map[string]bool) (map[string]string, error) {
func listGorootMergeLinks(goroot, tinygoroot string, overrides map[string]bool, config *compileopts.Config) (map[string]string, error) {
goSrc := filepath.Join(goroot, "src")
tinygoSrc := filepath.Join(tinygoroot, "src")
merges := make(map[string]string)

// buildContext is used to evaluate //go:build constraints on TinyGo
// source files. A TinyGo file that doesn't match the current target
// (e.g. a *_wasip2.go file in a wasip1 build) must not be treated as
// "TinyGo owns this directory" — otherwise wasip1 builds would lose
// upstream Go files at the same level.
bctx := build.Default
bctx.GOOS = config.GOOS()
bctx.GOARCH = config.GOARCH()
bctx.BuildTags = config.BuildTags()
bctx.Compiler = "gc"

for dir, merge := range overrides {
if !merge {
// Use the TinyGo version.
Expand All @@ -168,6 +181,14 @@ func listGorootMergeLinks(goroot, tinygoroot string, overrides map[string]bool)

// Link this file.
name := e.Name()
// Only count this file as a TinyGo override of the directory
// when its build tags match the current target. Files with a
// non-matching //go:build are invisible to this build anyway
// (the compiler would skip them), so they shouldn't cause
// upstream files to be dropped from the merge.
if matched, _ := bctx.MatchFile(tinygoDir, name); !matched {
continue
}
merges[filepath.Join("src", dir, name)] = filepath.Join(tinygoDir, name)

hasTinyGoFiles = true
Expand Down Expand Up @@ -246,6 +267,7 @@ func pathsToOverride(goMinor int, needsSyscallPackage bool) map[string]bool {
"internal/futex/": false,
"internal/fuzz/": false,
"internal/itoa": false,
"internal/poll/": false,
"internal/reflectlite/": false,
"internal/gclayout": false,
"internal/task/": false,
Expand Down
24 changes: 24 additions & 0 deletions src/internal/poll/errors_wasip.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//go:build wasip1 || wasip2

// Shared error sentinels for the wasip1 and wasip2 internal/poll
// implementations. The error values are part of the public API surface
// upstream net relies on; sharing them keeps fd_wasip1.go and
// fd_wasip2.go free of redundant declarations.

package poll

import "errors"

// ErrFileClosing is returned when a Read or Write is started on a closed FD.
var ErrFileClosing = errors.New("use of closed file")

// ErrNetClosing is returned for network operations on a closed FD.
var ErrNetClosing = errors.New("use of closed network connection")

// ErrDeadlineExceeded is returned by Read/Write when a deadline expired.
// Matches the error returned by os.IsTimeout-style helpers.
var ErrDeadlineExceeded = errors.New("i/o timeout")

// ErrNoDeadline is returned if SetDeadline is called on an FD whose
// underlying type does not support deadlines.
var ErrNoDeadline = errors.New("file type does not support deadline")
45 changes: 45 additions & 0 deletions src/internal/poll/export_test_wasip1.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//go:build wasip1

// Internal-test helpers exposed via go:linkname so user code can drive
// the deadline-aware Read/Write loop without becoming a stdlib package.
// Not part of the public API; the names are intentionally awkward to
// signal "for tests only".

package poll

import (
"syscall"
"time"
)

// pollTestReadWithDeadline opens a pollable FD wrapper for sysfd, sets
// a read deadline d into the future, calls Read once, and returns
// (n, err). Caller is responsible for closing sysfd.
//
//go:linkname pollTestReadWithDeadline
func pollTestReadWithDeadline(sysfd int, d time.Duration, p []byte) (int, error) {
fd := &FD{Sysfd: sysfd, IsStream: true}
// Best-effort init; ignore error so a caller using a not-fcntl-able FD
// (stdin under wazero, etc.) still gets to test the deadline path on
// whatever park behaviour the runtime gives.
_ = fd.Init("test", true)
if err := fd.SetReadDeadline(time.Now().Add(d)); err != nil {
return 0, err
}
return fd.Read(p)
}

// pollTestSetNonblock toggles O_NONBLOCK on a raw sysfd. Useful in
// tests when the caller wants to ensure the FD is in nonblocking mode
// before calling pollTestReadWithDeadline (Init is best-effort and may
// silently skip).
//
//go:linkname pollTestSetNonblock
func pollTestSetNonblock(sysfd int) error {
flags, err := syscall.Fcntl(sysfd, syscall.F_GETFL, 0)
if err != nil {
return err
}
_, err = syscall.Fcntl(sysfd, syscall.F_SETFL, flags|syscall.O_NONBLOCK)
return err
}
Loading
Loading