Skip to content

Commit cba5ecd

Browse files
committed
Merge branch 'master' into websocket-http2
# Conflicts: # http2/transport_test.go
2 parents 23eded4 + 334afa0 commit cba5ecd

19 files changed

+858
-116
lines changed

Diff for: README.md

+6-8
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,15 @@
22

33
[![Go Reference](https://pkg.go.dev/badge/golang.org/x/net.svg)](https://pkg.go.dev/golang.org/x/net)
44

5-
This repository holds supplementary Go networking libraries.
5+
This repository holds supplementary Go networking packages.
66

7-
## Download/Install
7+
## Report Issues / Send Patches
88

9-
The easiest way to install is to run `go get -u golang.org/x/net`. You can
10-
also manually git clone the repository to `$GOPATH/src/golang.org/x/net`.
9+
This repository uses Gerrit for code changes. To learn how to submit changes to
10+
this repository, see https://go.dev/doc/contribute.
1111

12-
## Report Issues / Send Patches
12+
The git repository is https://go.googlesource.com/net.
1313

14-
This repository uses Gerrit for code changes. To learn how to submit
15-
changes to this repository, see https://golang.org/doc/contribute.html.
1614
The main issue tracker for the net repository is located at
17-
https://github.com/golang/go/issues. Prefix your issue with "x/net:" in the
15+
https://go.dev/issues. Prefix your issue with "x/net:" in the
1816
subject line, so it is easy to find.

Diff for: go.mod

+4-4
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ module golang.org/x/net
33
go 1.18
44

55
require (
6-
golang.org/x/crypto v0.27.0
7-
golang.org/x/sys v0.25.0
8-
golang.org/x/term v0.24.0
9-
golang.org/x/text v0.18.0
6+
golang.org/x/crypto v0.29.0
7+
golang.org/x/sys v0.27.0
8+
golang.org/x/term v0.26.0
9+
golang.org/x/text v0.20.0
1010
)

Diff for: go.sum

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
2-
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
3-
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
4-
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
5-
golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM=
6-
golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
7-
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
8-
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
1+
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
2+
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
3+
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
4+
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
5+
golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
6+
golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E=
7+
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
8+
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=

Diff for: html/doc.go

+1-6
Original file line numberDiff line numberDiff line change
@@ -78,16 +78,11 @@ example, to process each anchor node in depth-first order:
7878
if err != nil {
7979
// ...
8080
}
81-
var f func(*html.Node)
82-
f = func(n *html.Node) {
81+
for n := range doc.Descendants() {
8382
if n.Type == html.ElementNode && n.Data == "a" {
8483
// Do something with n...
8584
}
86-
for c := n.FirstChild; c != nil; c = c.NextSibling {
87-
f(c)
88-
}
8985
}
90-
f(doc)
9186
9287
The relevant specifications include:
9388
https://html.spec.whatwg.org/multipage/syntax.html and

Diff for: html/example_test.go

+6-7
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5+
//go:build go1.23
6+
57
// This example demonstrates parsing HTML data and walking the resulting tree.
68
package html_test
79

@@ -11,6 +13,7 @@ import (
1113
"strings"
1214

1315
"golang.org/x/net/html"
16+
"golang.org/x/net/html/atom"
1417
)
1518

1619
func ExampleParse() {
@@ -19,21 +22,17 @@ func ExampleParse() {
1922
if err != nil {
2023
log.Fatal(err)
2124
}
22-
var f func(*html.Node)
23-
f = func(n *html.Node) {
24-
if n.Type == html.ElementNode && n.Data == "a" {
25+
for n := range doc.Descendants() {
26+
if n.Type == html.ElementNode && n.DataAtom == atom.A {
2527
for _, a := range n.Attr {
2628
if a.Key == "href" {
2729
fmt.Println(a.Val)
2830
break
2931
}
3032
}
3133
}
32-
for c := n.FirstChild; c != nil; c = c.NextSibling {
33-
f(c)
34-
}
3534
}
36-
f(doc)
35+
3736
// Output:
3837
// foo
3938
// /bar/baz

Diff for: html/iter.go

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright 2024 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
//go:build go1.23
6+
7+
package html
8+
9+
import "iter"
10+
11+
// Ancestors returns an iterator over the ancestors of n, starting with n.Parent.
12+
//
13+
// Mutating a Node or its parents while iterating may have unexpected results.
14+
func (n *Node) Ancestors() iter.Seq[*Node] {
15+
_ = n.Parent // eager nil check
16+
17+
return func(yield func(*Node) bool) {
18+
for p := n.Parent; p != nil && yield(p); p = p.Parent {
19+
}
20+
}
21+
}
22+
23+
// ChildNodes returns an iterator over the immediate children of n,
24+
// starting with n.FirstChild.
25+
//
26+
// Mutating a Node or its children while iterating may have unexpected results.
27+
func (n *Node) ChildNodes() iter.Seq[*Node] {
28+
_ = n.FirstChild // eager nil check
29+
30+
return func(yield func(*Node) bool) {
31+
for c := n.FirstChild; c != nil && yield(c); c = c.NextSibling {
32+
}
33+
}
34+
35+
}
36+
37+
// Descendants returns an iterator over all nodes recursively beneath
38+
// n, excluding n itself. Nodes are visited in depth-first preorder.
39+
//
40+
// Mutating a Node or its descendants while iterating may have unexpected results.
41+
func (n *Node) Descendants() iter.Seq[*Node] {
42+
_ = n.FirstChild // eager nil check
43+
44+
return func(yield func(*Node) bool) {
45+
n.descendants(yield)
46+
}
47+
}
48+
49+
func (n *Node) descendants(yield func(*Node) bool) bool {
50+
for c := range n.ChildNodes() {
51+
if !yield(c) || !c.descendants(yield) {
52+
return false
53+
}
54+
}
55+
return true
56+
}

Diff for: html/iter_test.go

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// Copyright 2024 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
//go:build go1.23
6+
7+
package html
8+
9+
import (
10+
"strings"
11+
"testing"
12+
)
13+
14+
func TestNode_ChildNodes(t *testing.T) {
15+
tests := []struct {
16+
in string
17+
want string
18+
}{
19+
{"", ""},
20+
{"<a></a>", "a"},
21+
{"a", "a"},
22+
{"<a></a><!--b-->", "a b"},
23+
{"a<b></b>c", "a b c"},
24+
{"a<b><!--c--></b>d", "a b d"},
25+
{"<a><b>c<!--d-->e</b></a>f<!--g--><h>i</h>", "a f g h"},
26+
}
27+
for _, test := range tests {
28+
doc, err := Parse(strings.NewReader(test.in))
29+
if err != nil {
30+
t.Fatal(err)
31+
}
32+
// Drill to <html><head></head><body>
33+
n := doc.FirstChild.FirstChild.NextSibling
34+
var results []string
35+
for c := range n.ChildNodes() {
36+
results = append(results, c.Data)
37+
}
38+
if got := strings.Join(results, " "); got != test.want {
39+
t.Errorf("ChildNodes = %q, want %q", got, test.want)
40+
}
41+
}
42+
}
43+
44+
func TestNode_Descendants(t *testing.T) {
45+
tests := []struct {
46+
in string
47+
want string
48+
}{
49+
{"", ""},
50+
{"<a></a>", "a"},
51+
{"<a><b></b></a>", "a b"},
52+
{"<a>b</a>", "a b"},
53+
{"<a><!--b--></a>", "a b"},
54+
{"<a>b<c></c>d</a>", "a b c d"},
55+
{"<a>b<c><!--d--></c>e</a>", "a b c d e"},
56+
{"<a><b><c>d<!--e-->f</c></b>g<!--h--><i>j</i></a>", "a b c d e f g h i j"},
57+
}
58+
for _, test := range tests {
59+
doc, err := Parse(strings.NewReader(test.in))
60+
if err != nil {
61+
t.Fatal(err)
62+
}
63+
// Drill to <html><head></head><body>
64+
n := doc.FirstChild.FirstChild.NextSibling
65+
var results []string
66+
for c := range n.Descendants() {
67+
results = append(results, c.Data)
68+
}
69+
if got := strings.Join(results, " "); got != test.want {
70+
t.Errorf("Descendants = %q; want: %q", got, test.want)
71+
}
72+
}
73+
}
74+
75+
func TestNode_Ancestors(t *testing.T) {
76+
for _, size := range []int{0, 1, 2, 10, 100, 10_000} {
77+
n := buildChain(size)
78+
nParents := 0
79+
for _ = range n.Ancestors() {
80+
nParents++
81+
}
82+
if nParents != size {
83+
t.Errorf("number of Ancestors = %d; want: %d", nParents, size)
84+
}
85+
}
86+
}
87+
88+
func buildChain(size int) *Node {
89+
child := new(Node)
90+
for range size {
91+
parent := child
92+
child = new(Node)
93+
parent.AppendChild(child)
94+
}
95+
return child
96+
}

Diff for: html/node.go

+4
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ var scopeMarker = Node{Type: scopeMarkerNode}
3838
// that it looks like "a<b" rather than "a&lt;b". For element nodes, DataAtom
3939
// is the atom for Data, or zero if Data is not a known tag name.
4040
//
41+
// Node trees may be navigated using the link fields (Parent,
42+
// FirstChild, and so on) or a range loop over iterators such as
43+
// [Node.Descendants].
44+
//
4145
// An empty Namespace implies a "http://www.w3.org/1999/xhtml" namespace.
4246
// Similarly, "math" is short for "http://www.w3.org/1998/Math/MathML", and
4347
// "svg" is short for "http://www.w3.org/2000/svg".

Diff for: http2/client_conn_pool.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ package http2
88

99
import (
1010
"context"
11-
"crypto/tls"
1211
"errors"
12+
"net"
1313
"net/http"
1414
"sync"
1515
)
@@ -158,7 +158,7 @@ func (c *dialCall) dial(ctx context.Context, addr string) {
158158
// This code decides which ones live or die.
159159
// The return value used is whether c was used.
160160
// c is never closed.
161-
func (p *clientConnPool) addConnIfNeeded(key string, t *Transport, c *tls.Conn) (used bool, err error) {
161+
func (p *clientConnPool) addConnIfNeeded(key string, t *Transport, c net.Conn) (used bool, err error) {
162162
p.mu.Lock()
163163
for _, cc := range p.conns[key] {
164164
if cc.CanTakeNewRequest() {
@@ -194,8 +194,8 @@ type addConnCall struct {
194194
err error
195195
}
196196

197-
func (c *addConnCall) run(t *Transport, key string, tc *tls.Conn) {
198-
cc, err := t.NewClientConn(tc)
197+
func (c *addConnCall) run(t *Transport, key string, nc net.Conn) {
198+
cc, err := t.NewClientConn(nc)
199199

200200
p := c.p
201201
p.mu.Lock()

Diff for: http2/clientconn_test.go

+23-7
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ package http2
1010
import (
1111
"bytes"
1212
"context"
13+
"crypto/tls"
1314
"fmt"
1415
"io"
1516
"net/http"
@@ -112,27 +113,40 @@ func newTestClientConnFromClientConn(t *testing.T, cc *ClientConn) *testClientCo
112113
cc: cc,
113114
group: cc.t.transportTestHooks.group.(*synctestGroup),
114115
}
115-
cli, srv := synctestNetPipe(tc.group)
116+
117+
// srv is the side controlled by the test.
118+
var srv *synctestNetConn
119+
if cc.tconn == nil {
120+
// If cc.tconn is nil, we're being called with a new conn created by the
121+
// Transport's client pool. This path skips dialing the server, and we
122+
// create a test connection pair here.
123+
cc.tconn, srv = synctestNetPipe(tc.group)
124+
} else {
125+
// If cc.tconn is non-nil, we're in a test which provides a conn to the
126+
// Transport via a TLSNextProto hook. Extract the test connection pair.
127+
if tc, ok := cc.tconn.(*tls.Conn); ok {
128+
// Unwrap any *tls.Conn to the underlying net.Conn,
129+
// to avoid dealing with encryption in tests.
130+
cc.tconn = tc.NetConn()
131+
}
132+
srv = cc.tconn.(*synctestNetConn).peer
133+
}
134+
116135
srv.SetReadDeadline(tc.group.Now())
117136
srv.autoWait = true
118137
tc.netconn = srv
119138
tc.enc = hpack.NewEncoder(&tc.encbuf)
120-
121-
// all writes and reads are finished.
122-
//
123-
// cli is the ClientConn's side, srv is the side controlled by the test.
124-
cc.tconn = cli
125139
tc.fr = NewFramer(srv, srv)
126140
tc.testConnFramer = testConnFramer{
127141
t: t,
128142
fr: tc.fr,
129143
dec: hpack.NewDecoder(initialHeaderTableSize, nil),
130144
}
131-
132145
tc.fr.SetMaxReadFrameSize(10 << 20)
133146
t.Cleanup(func() {
134147
tc.closeWrite()
135148
})
149+
136150
return tc
137151
}
138152

@@ -503,6 +517,8 @@ func newTestTransport(t *testing.T, opts ...any) *testTransport {
503517
o(tr.t1)
504518
case func(*Transport):
505519
o(tr)
520+
case *Transport:
521+
tr = o
506522
}
507523
}
508524
tt.tr = tr

Diff for: http2/http2_test.go

+8
Original file line numberDiff line numberDiff line change
@@ -283,3 +283,11 @@ func TestNoUnicodeStrings(t *testing.T) {
283283
t.Fatal(err)
284284
}
285285
}
286+
287+
// must returns v if err is nil, or panics otherwise.
288+
func must[T any](v T, err error) T {
289+
if err != nil {
290+
panic(err)
291+
}
292+
return v
293+
}

0 commit comments

Comments
 (0)