Repository: goplus/gop
Pull request #1521 (2023-11-07 04:30:37)

cl: preloadGopFile no change classfile ast


Patch:
diff --git a/cl/classfile.go b/cl/classfile.go
index 250fe833..7c6b5f1c 100644
--- a/cl/classfile.go
+++ b/cl/classfile.go
@@ -139,18 +139,17 @@ func getStringConst(spx *gox.PkgRef, name string) string {
 	return ""
 }
 
-func getFields(f *ast.File) (specs []ast.Spec) {
+func getFields(f *ast.File) []ast.Spec {
 	for _, decl := range f.Decls {
 		if g, ok := decl.(*ast.GenDecl); ok {
 			if g.Tok == token.VAR {
-				specs, g.Specs = g.Specs, nil
-				return
+				return g.Specs
 			}
 			continue
 		}
 		break
 	}
-	return
+	return nil
 }
 
 func setBodyHandler(ctx *blockCtx) {
diff --git a/cl/compile.go b/cl/compile.go
index 67d4da0f..25a34f27 100644
--- a/cl/compile.go
+++ b/cl/compile.go
@@ -758,21 +758,34 @@ func preloadGopFile(p *gox.Package, ctx *blockCtx, file string, f *ast.File, con
 						tags = append(tags, "")
 					}
 				}
+				rec := ctx.recorder()
 				for _, v := range specs {
 					spec := v.(*ast.ValueSpec)
-					var embed bool
-					if spec.Names == nil {
-						embed = true
-						v := parseTypeEmbedName(spec.Type)
-						spec.Names = []*ast.Ident{v}
-					}
 					typ := toType(ctx, spec.Type)
-					for _, name := range spec.Names {
-						if chk.chkRedecl(ctx, name.Name, name.Pos()) {
+					tag := toFieldTag(spec.Tag)
+					if len(spec.Names) == 0 {
+						name := parseTypeEmbedName(spec.Type)
+						if chk.chkRedecl(ctx, name.Name, spec.Type.Pos()) {
 							continue
 						}
-						flds = append(flds, types.NewField(name.Pos(), pkg, name.Name, typ, embed))
-						tags = append(tags, toFieldTag(spec.Tag))
+						fld := types.NewField(spec.Type.Pos(), pkg, name.Name, typ, true)
+						if rec != nil {
+							rec.Def(name, fld)
+						}
+						flds = append(flds, fld)
+						tags = append(tags, tag)
+					} else {
+						for _, name := range spec.Names {
+							if chk.chkRedecl(ctx, name.Name, name.Pos()) {
+								continue
+							}
+							fld := types.NewField(name.Pos(), pkg, name.Name, typ, false)
+							if rec != nil {
+								rec.Def(name, fld)
+							}
+							flds = append(flds, fld)
+							tags = append(tags, tag)
+						}
 					}
 				}
 				decl.InitType(p, types.NewStruct(flds, tags))
@@ -834,6 +847,10 @@ func preloadFile(p *gox.Package, ctx *blockCtx, file string, f *ast.File, gopFil
 	goFile := genGoFile(file, gopFile)
 	old, _ := p.SetCurFile(goFile, true)
 	defer p.RestoreCurFile(old)
+	var skipClassFields bool
+	if f.IsClass {
+		skipClassFields = true
+	}
 	for _, decl := range f.Decls {
 		switch d := decl.(type) {
 		case *ast.FuncDecl:
@@ -970,6 +987,10 @@ func preloadFile(p *gox.Package, ctx *blockCtx, file string, f *ast.File, gopFil
 					})
 				}
 			case token.VAR:
+				if skipClassFields {
+					skipClassFields = false
+					continue
+				}
 				for _, spec := range d.Specs {
 					vSpec := spec.(*ast.ValueSpec)
 					if debugLoad {
diff --git a/x/jsonrpc2/conn.go b/x/jsonrpc2/conn.go
deleted file mode 100644
index 8d3fd93d..00000000
--- a/x/jsonrpc2/conn.go
+++ /dev/null
@@ -1,809 +0,0 @@
-/*
- * Copyright (c) 2023 The GoPlus Authors (goplus.org). All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// 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.
-
-package jsonrpc2
-
-import (
-	"context"
-	"encoding/json"
-	"errors"
-	"fmt"
-	"io"
-	"log"
-	"sync"
-	"sync/atomic"
-	"time"
-)
-
-// Binder builds a connection configuration.
-// This may be used in servers to generate a new configuration per connection.
-// ConnectionOptions itself implements Binder returning itself unmodified, to
-// allow for the simple cases where no per connection information is needed.
-type Binder interface {
-	// Bind returns the ConnectionOptions to use when establishing the passed-in
-	// Connection.
-	//
-	// The connection is not ready to use when Bind is called,
-	// but Bind may close it without reading or writing to it.
-	Bind(context.Context, *Connection) ConnectionOptions
-}
-
-// A BinderFunc implements the Binder interface for a standalone Bind function.
-type BinderFunc func(context.Context, *Connection) ConnectionOptions
-
-func (f BinderFunc) Bind(ctx context.Context, c *Connection) ConnectionOptions {
-	return f(ctx, c)
-}
-
-var _ Binder = BinderFunc(nil)
-
-// ConnectionOptions holds the options for new connections.
-type ConnectionOptions struct {
-	// Framer allows control over the message framing and encoding.
-	// If nil, HeaderFramer will be used.
-	Framer Framer
-	// Preempter allows registration of a pre-queue message handler.
-	// If nil, no messages will be preempted.
-	Preempter Preempter
-	// Handler is used as the queued message handler for inbound messages.
-	// If nil, all responses will be ErrNotHandled.
-	Handler Handler
-	// OnInternalError, if non-nil, is called with any internal errors that occur
-	// while serving the connection, such as protocol errors or invariant
-	// violations. (If nil, internal errors result in panics.)
-	OnInternalError func(error)
-}
-
-// Connection manages the jsonrpc2 protocol, connecting responses back to their
-// calls.
-// Connection is bidirectional; it does not have a designated server or client
-// end.
-type Connection struct {
-	seq int64 // must only be accessed using atomic operations
-
-	stateMu sync.Mutex
-	state   inFlightState // accessed only in updateInFlight
-	done    chan struct{} // closed (under stateMu) when state.closed is true and all goroutines have completed
-
-	writer chan Writer // 1-buffered; stores the writer when not in use
-
-	handler Handler
-
-	onInternalError func(error)
-	onDone          func()
-}
-
-// inFlightState records the state of the incoming and outgoing calls on a
-// Connection.
-type inFlightState struct {
-	connClosing bool  // true when the Connection's Close method has been called
-	reading     bool  // true while the readIncoming goroutine is running
-	readErr     error // non-nil when the readIncoming goroutine exits (typically io.EOF)
-	writeErr    error // non-nil if a call to the Writer has failed with a non-canceled Context
-
-	// closer shuts down and cleans up the Reader and Writer state, ideally
-	// interrupting any Read or Write call that is currently blocked. It is closed
-	// when the state is idle and one of: connClosing is true, readErr is non-nil,
-	// or writeErr is non-nil.
-	//
-	// After the closer has been invoked, the closer field is set to nil
-	// and the closeErr field is simultaneously set to its result.
-	closer   io.Closer
-	closeErr error // error returned from closer.Close
-
-	outgoingCalls         map[ID]*AsyncCall // calls only
-	outgoingNotifications int               // # of notifications awaiting "write"
-
-	// incoming stores the total number of incoming calls and notifications
-	// that have not yet written or processed a result.
-	incoming int
-
-	incomingByID map[ID]*incomingRequest // calls only
-
-	// handlerQueue stores the backlog of calls and notifications that were not
-	// already handled by a preempter.
-	// The queue does not include the request currently being handled (if any).
-	handlerQueue   []*incomingRequest
-	handlerRunning bool
-}
-
-// updateInFlight locks the state of the connection's in-flight requests, allows
-// f to mutate that state, and closes the connection if it is idle and either
-// is closing or has a read or write error.
-func (c *Connection) updateInFlight(f func(*inFlightState)) {
-	c.stateMu.Lock()
-	defer c.stateMu.Unlock()
-
-	s := &c.state
-
-	f(s)
-
-	select {
-	case <-c.done:
-		// The connection was already completely done at the start of this call to
-		// updateInFlight, so it must remain so. (The call to f should have noticed
-		// that and avoided making any updates that would cause the state to be
-		// non-idle.)
-		if !s.idle() {
-			panic("jsonrpc2_v2: updateInFlight transitioned to non-idle when already done")
-		}
-		return
-	default:
-	}
-
-	if s.idle() && s.shuttingDown(ErrUnknown) != nil {
-		if Verbose {
-			log.Println("==> Connection.updateInFlight: shuttingDown")
-		}
-		if s.closer != nil {
-			s.closeErr = s.closer.Close()
-			s.closer = nil // prevent duplicate Close calls
-		}
-		if Verbose {
-			log.Println("==> Connection.updateInFlight: s.reading -", s.reading)
-		}
-		if s.reading {
-			// The readIncoming goroutine is still running. Our call to Close should
-			// cause it to exit soon, at which point it will make another call to
-			// updateInFlight, set s.reading to false, and mark the Connection done.
-		} else {
-			// The readIncoming goroutine has exited, or never started to begin with.
-			// Since everything else is idle, we're completely done.
-			if c.onDone != nil {
-				c.onDone()
-			}
-			close(c.done)
-		}
-	}
-}
-
-// idle reports whether the connection is in a state with no pending calls or
-// notifications.
-//
-// If idle returns true, the readIncoming goroutine may still be running,
-// but no other goroutines are doing work on behalf of the connection.
-func (s *inFlightState) idle() bool {
-	return len(s.outgoingCalls) == 0 && s.outgoingNotifications == 0 && s.incoming == 0 && !s.handlerRunning
-}
-
-// shuttingDown reports whether the connection is in a state that should
-// disallow new (incoming and outgoing) calls. It returns either nil or
-// an error that is or wraps the provided errClosing.
-func (s *inFlightState) shuttingDown(errClosing error) error {
-	if s.connClosing {
-		// If Close has been called explicitly, it doesn't matter what state the
-		// Reader and Writer are in: we shouldn't be starting new work because the
-		// caller told us not to start new work.
-		return errClosing
-	}
-	if s.readErr != nil {
-		// If the read side of the connection is broken, we cannot read new call
-		// requests, and cannot read responses to our outgoing calls.
-		return fmt.Errorf("%w: %v", errClosing, s.readErr)
-	}
-	if s.writeErr != nil {
-		// If the write side of the connection is broken, we cannot write responses
-		// for incoming calls, and cannot write requests for outgoing calls.
-		return fmt.Errorf("%w: %v", errClosing, s.writeErr)
-	}
-	return nil
-}
-
-// incomingRequest is used to track an incoming request as it is being handled
-type incomingRequest struct {
-	*Request // the request being processed
-	ctx      context.Context
-	cancel   context.CancelFunc
-}
-
-// newConnection creates a new connection and runs it.
-//
-// This is used by the Dial and Serve functions to build the actual connection.
-//
-// The connection is closed automatically (and its resources cleaned up) when
-// the last request has completed after the underlying ReadWriteCloser breaks,
-// but it may be stopped earlier by calling Close (for a clean shutdown).
-func newConnection(bindCtx context.Context, rwc io.ReadWriteCloser, binder Binder, onDone func()) *Connection {
-	// TODO: Should we create a new event span here?
-	// This will propagate cancellation from ctx; should it?
-	ctx := notDone{bindCtx}
-
-	c := &Connection{
-		state:  inFlightState{closer: rwc},
-		done:   make(chan struct{}),
-		writer: make(chan Writer, 1),
-		onDone: onDone,
-	}
-	// It's tempting to set a finalizer on c to verify that the state has gone
-	// idle when the connection becomes unreachable. Unfortunately, the Binder
-	// interface makes that unsafe: it allows the Handler to close over the
-	// Connection, which could create a reference cycle that would cause the
-	// Connection to become uncollectable.
-
-	options := binder.Bind(bindCtx, c)
-	framer := options.Framer
-	if framer == nil {
-		framer = HeaderFramer()
-	}
-	c.handler = options.Handler
-	if c.handler == nil {
-		c.handler = defaultHandler{}
-	}
-	c.onInternalError = options.OnInternalError
-	if c.onInternalError == nil {
-		c.onInternalError = defaultHandleError
-	}
-
-	c.writer <- framer.Writer(rwc)
-	reader := framer.Reader(rwc)
-
-	c.updateInFlight(func(s *inFlightState) {
-		select {
-		case <-c.done:
-			// Bind already closed the connection; don't start a goroutine to read it.
-			return
-		default:
-		}
-
-		// The goroutine started here will continue until the underlying stream is closed.
-		//
-		// (If the Binder closed the Connection already, this should error out and
-		// return almost immediately.)
-		s.reading = true
-		go c.readIncoming(ctx, reader, options.Preempter)
-	})
-	return c
-}
-
-// Notify invokes the target method but does not wait for a response.
-// The params will be marshaled to JSON before sending over the wire, and will
-// be handed to the method invoked.
-func (c *Connection) Notify(ctx context.Context, method string, params interface{}) (err error) {
-	attempted := false
-
-	defer func() {
-		if attempted {
-			c.updateInFlight(func(s *inFlightState) {
-				s.outgoingNotifications--
-			})
-		}
-	}()
-
-	if debugCall {
-		log.Println("==> Connection.Notify", method, "params:", params)
-	}
-
-	c.updateInFlight(func(s *inFlightState) {
-		// If the connection is shutting down, allow outgoing notifications only if
-		// there is at least one call still in flight. The number of calls in flight
-		// cannot increase once shutdown begins, and allowing outgoing notifications
-		// may permit notifications that will cancel in-flight calls.
-		if len(s.outgoingCalls) == 0 && len(s.incomingByID) == 0 {
-			err = s.shuttingDown(ErrClientClosing)
-			if err != nil {
-				return
-			}
-		}
-		s.outgoingNotifications++
-		attempted = true
-	})
-	if err != nil {
-		return err
-	}
-
-	notify, err := NewNotification(method, params)
-	if err != nil {
-		return fmt.Errorf("marshaling notify parameters: %v", err)
-	}
-
-	err = c.write(ctx, notify)
-	if debugCall {
-		log.Println("==> Connection.write:", notify.Method, err)
-	}
-	return
-}
-
-// Call invokes the target method and returns an object that can be used to await the response.
-// The params will be marshaled to JSON before sending over the wire, and will
-// be handed to the method invoked.
-// You do not have to wait for the response, it can just be ignored if not needed.
-// If sending the call failed, the response will be ready and have the error in it.
-func (c *Connection) Call(ctx context.Context, method string, params interface{}) *AsyncCall {
-	if debugCall {
-		log.Println("==> Connection.Call", method, "params:", params)
-	}
-	// Generate a new request identifier.
-	id := Int64ID(atomic.AddInt64(&c.seq, 1))
-	ac := &AsyncCall{
-		id:    id,
-		ready: make(chan struct{}),
-	}
-	// When this method returns, either ac is retired, or the request has been
-	// written successfully and the call is awaiting a response (to be provided by
-	// the readIncoming goroutine).
-
-	call, err := NewCall(ac.id, method, params)
-	if err != nil {
-		ac.retire(&Response{ID: id, Error: fmt.Errorf("marshaling call parameters: %w", err)})
-		return ac
-	}
-
-	c.updateInFlight(func(s *inFlightState) {
-		err = s.shuttingDown(ErrClientClosing)
-		if err != nil {
-			return
-		}
-		if s.outgoingCalls == nil {
-			s.outgoingCalls = make(map[ID]*AsyncCall)
-		}
-		s.outgoingCalls[ac.id] = ac
-	})
-	if err != nil {
-		ac.retire(&Response{ID: id, Error: err})
-		return ac
-	}
-
-	err = c.write(ctx, call)
-	if debugCall {
-		log.Println("==> Connection.write:", call.ID, call.Method, err)
-	}
-	if err != nil {
-		// Sending failed. We will never get a response, so deliver a fake one if it
-		// wasn't already retired by the connection breaking.
-		c.updateInFlight(func(s *inFlightState) {
-			if s.outgoingCalls[ac.id] == ac {
-				delete(s.outgoingCalls, ac.id)
-				ac.retire(&Response{ID: id, Error: err})
-			} else {
-				// ac was already retired by the readIncoming goroutine:
-				// perhaps our write raced with the Read side of the connection breaking.
-				_ = 0
-			}
-		})
-	}
-	return ac
-}
-
-type AsyncCall struct {
-	id       ID
-	ready    chan struct{} // closed after response has been set
-	response *Response
-}
-
-// ID used for this call.
-// This can be used to cancel the call if needed.
-func (ac *AsyncCall) ID() ID { return ac.id }
-
-// IsReady can be used to check if the result is already prepared.
-// This is guaranteed to return true on a result for which Await has already
-// returned, or a call that failed to send in the first place.
-func (ac *AsyncCall) IsReady() bool {
-	select {
-	case <-ac.ready:
-		return true
-	default:
-		return false
-	}
-}
-
-// retire processes the response to the call.
-func (ac *AsyncCall) retire(response *Response) {
-	select {
-	case <-ac.ready:
-		panic(fmt.Sprintf("jsonrpc2: retire called twice for ID %v", ac.id))
-	default:
-	}
-
-	ac.response = response
-	close(ac.ready)
-}
-
-// Await waits for (and decodes) the results of a Call.
-// The response will be unmarshaled from JSON into the result.
-func (ac *AsyncCall) Await(ctx context.Context, result interface{}) error {
-	if Verbose {
-		log.Println("==> AsyncCall.Await", ac.id)
-	}
-	select {
-	case <-ctx.Done():
-		return ctx.Err()
-	case <-ac.ready:
-	}
-	if e := ac.response.Error; e != nil {
-		if Verbose {
-			log.Println("==> AsyncCall.Await error:", ac.id, e)
-		}
-		return e
-	}
-	ret := ac.response.Result
-	if Verbose {
-		log.Println("==> AsyncCall.Await ret:", ac.id, string(ret))
-	}
-	if result == nil {
-		return nil
-	}
-	return json.Unmarshal(ret, result)
-}
-
-// Respond delivers a response to an incoming Call.
-//
-// Respond must be called exactly once for any message for which a handler
-// returns ErrAsyncResponse. It must not be called for any other message.
-func (c *Connection) Respond(id ID, result interface{}, err error) error {
-	var req *incomingRequest
-	c.updateInFlight(func(s *inFlightState) {
-		req = s.incomingByID[id]
-	})
-	if req == nil {
-		return c.internalErrorf("Request not found for ID %v", id)
-	}
-
-	if err == ErrAsyncResponse {
-		// Respond is supposed to supply the asynchronous response, so it would be
-		// confusing to call Respond with an error that promises to call Respond
-		// again.
-		err = c.internalErrorf("Respond called with ErrAsyncResponse for %q", req.Method)
-	}
-	return c.processResult("Respond", req, result, err)
-}
-
-// Cancel cancels the Context passed to the Handle call for the inbound message
-// with the given ID.
-//
-// Cancel will not complain if the ID is not a currently active message, and it
-// will not cause any messages that have not arrived yet with that ID to be
-// cancelled.
-func (c *Connection) Cancel(id ID) {
-	var req *incomingRequest
-	c.updateInFlight(func(s *inFlightState) {
-		req = s.incomingByID[id]
-	})
-	if req != nil {
-		req.cancel()
-	}
-}
-
-// Wait blocks until the connection is fully closed, but does not close it.
-func (c *Connection) Wait() error {
-	if Verbose {
-		log.Println("==> Connection.Wait start")
-	}
-	var err error
-	<-c.done
-	c.updateInFlight(func(s *inFlightState) {
-		err = s.closeErr
-	})
-	if Verbose {
-		log.Println("==> Connection.Wait end:", err)
-	}
-	return err
-}
-
-// Close stops accepting new requests, waits for in-flight requests and enqueued
-// Handle calls to complete, and then closes the underlying stream.
-//
-// After the start of a Close, notification requests (that lack IDs and do not
-// receive responses) will continue to be passed to the Preempter, but calls
-// with IDs will receive immediate responses with ErrServerClosing, and no new
-// requests (not even notifications!) will be enqueued to the Handler.
-func (c *Connection) Close() error {
-	// Stop handling new requests, and interrupt the reader (by closing the
-	// connection) as soon as the active requests finish.
-	c.updateInFlight(func(s *inFlightState) { s.connClosing = true })
-
-	return c.Wait()
-}
-
-// readIncoming collects inbound messages from the reader and delivers them, either responding
-// to outgoing calls or feeding requests to the queue.
-func (c *Connection) readIncoming(ctx context.Context, reader Reader, preempter Preempter) {
-	var err error
-	for {
-		var (
-			msg Message
-			n   int64
-		)
-		msg, n, err = reader.Read(ctx)
-		if err != nil {
-			break
-		}
-
-		switch msg := msg.(type) {
-		case *Request:
-			c.acceptRequest(ctx, msg, n, preempter)
-
-		case *Response:
-			if Verbose {
-				log.Println("==> readIncoming Response:", msg.ID)
-			}
-			c.updateInFlight(func(s *inFlightState) {
-				if ac, ok := s.outgoingCalls[msg.ID]; ok {
-					delete(s.outgoingCalls, msg.ID)
-					ac.retire(msg)
-				} else {
-					// TODO: How should we report unexpected responses?
-					_ = 0
-				}
-			})
-			if Verbose {
-				log.Println("==> readIncoming: updateInFlight -", msg.ID)
-			}
-
-		default:
-			c.internalErrorf("Read returned an unexpected message of type %T", msg)
-		}
-	}
-
-	c.updateInFlight(func(s *inFlightState) {
-		if Verbose {
-			log.Println("==> readIncoming: updateInFlight s.reading - false")
-		}
-		s.reading = false
-		s.readErr = err
-
-		// Retire any outgoing requests that were still in flight: with the Reader no
-		// longer being processed, they necessarily cannot receive a response.
-		for id, ac := range s.outgoingCalls {
-			ac.retire(&Response{ID: id, Error: err})
-		}
-		s.outgoingCalls = nil
-	})
-}
-
-// acceptRequest either handles msg synchronously or enqueues it to be handled
-// asynchronously.
-func (c *Connection) acceptRequest(ctx context.Context, msg *Request, msgBytes int64, preempter Preempter) {
-	// In theory notifications cannot be cancelled, but we build them a cancel
-	// context anyway.
-	ctx, cancel := context.WithCancel(ctx)
-	req := &incomingRequest{
-		Request: msg,
-		ctx:     ctx,
-		cancel:  cancel,
-	}
-
-	// If the request is a call, add it to the incoming map so it can be
-	// cancelled (or responded) by ID.
-	var err error
-	c.updateInFlight(func(s *inFlightState) {
-		s.incoming++
-
-		if req.IsCall() {
-			if s.incomingByID[req.ID] != nil {
-				err = fmt.Errorf("%w: request ID %v already in use", ErrInvalidRequest, req.ID)
-				req.ID = ID{} // Don't misattribute this error to the existing request.
-				return
-			}
-
-			if s.incomingByID == nil {
-				s.incomingByID = make(map[ID]*incomingRequest)
-			}
-			s.incomingByID[req.ID] = req
-
-			// When shutting down, reject all new Call requests, even if they could
-			// theoretically be handled by the preempter. The preempter could return
-			// ErrAsyncResponse, which would increase the amount of work in flight
-			// when we're trying to ensure that it strictly decreases.
-			err = s.shuttingDown(ErrServerClosing)
-		}
-	})
-	if err != nil {
-		c.processResult("acceptRequest", req, nil, err)
-		return
-	}
-
-	if preempter != nil {
-		result, err := preempter.Preempt(req.ctx, req.Request)
-
-		if req.IsCall() && errors.Is(err, ErrAsyncResponse) {
-			// This request will remain in flight until Respond is called for it.
-			return
-		}
-
-		if !errors.Is(err, ErrNotHandled) {
-			c.processResult("Preempt", req, result, err)
-			return
-		}
-	}
-
-	c.updateInFlight(func(s *inFlightState) {
-		// If the connection is shutting down, don't enqueue anything to the
-		// handler — not even notifications. That ensures that if the handler
-		// continues to make progress, it will eventually become idle and
-		// close the connection.
-		err = s.shuttingDown(ErrServerClosing)
-		if err != nil {
-			return
-		}
-
-		// We enqueue requests that have not been preempted to an unbounded slice.
-		// Unfortunately, we cannot in general limit the size of the handler
-		// queue: we have to read every response that comes in on the wire
-		// (because it may be responding to a request issued by, say, an
-		// asynchronous handler), and in order to get to that response we have
-		// to read all of the requests that came in ahead of it.
-		s.handlerQueue = append(s.handlerQueue, req)
-		if !s.handlerRunning {
-			// We start the handleAsync goroutine when it has work to do, and let it
-			// exit when the queue empties.
-			//
-			// Otherwise, in order to synchronize the handler we would need some other
-			// goroutine (probably readIncoming?) to explicitly wait for handleAsync
-			// to finish, and that would complicate error reporting: either the error
-			// report from the goroutine would be blocked on the handler emptying its
-			// queue (which was tried, and introduced a deadlock detected by
-			// TestCloseCallRace), or the error would need to be reported separately
-			// from synchronizing completion. Allowing the handler goroutine to exit
-			// when idle seems simpler than trying to implement either of those
-			// alternatives correctly.
-			s.handlerRunning = true
-			go c.handleAsync()
-		}
-	})
-	if err != nil {
-		c.processResult("acceptRequest", req, nil, err)
-	}
-}
-
-// handleAsync invokes the handler on the requests in the handler queue
-// sequentially until the queue is empty.
-func (c *Connection) handleAsync() {
-	for {
-		var req *incomingRequest
-		c.updateInFlight(func(s *inFlightState) {
-			if len(s.handlerQueue) > 0 {
-				req, s.handlerQueue = s.handlerQueue[0], s.handlerQueue[1:]
-			} else {
-				s.handlerRunning = false
-			}
-		})
-		if req == nil {
-			return
-		}
-
-		// Only deliver to the Handler if not already canceled.
-		if err := req.ctx.Err(); err != nil {
-			c.updateInFlight(func(s *inFlightState) {
-				if s.writeErr != nil {
-					// Assume that req.ctx was canceled due to s.writeErr.
-					// TODO(#51365): use a Context API to plumb this through req.ctx.
-					err = fmt.Errorf("%w: %v", ErrServerClosing, s.writeErr)
-				}
-			})
-			c.processResult("handleAsync", req, nil, err)
-			continue
-		}
-
-		result, err := c.handler.Handle(req.ctx, req.Request)
-		c.processResult(c.handler, req, result, err)
-	}
-}
-
-// processResult processes the result of a request and, if appropriate, sends a response.
-func (c *Connection) processResult(from interface{}, req *incomingRequest, result interface{}, err error) error {
-	switch err {
-	case ErrAsyncResponse:
-		if !req.IsCall() {
-			return c.internalErrorf("%#v returned ErrAsyncResponse for a %q Request without an ID", from, req.Method)
-		}
-		return nil // This request is still in flight, so don't record the result yet.
-	case ErrNotHandled, ErrMethodNotFound:
-		// Add detail describing the unhandled method.
-		err = fmt.Errorf("%w: %q", ErrMethodNotFound, req.Method)
-	}
-
-	if result != nil && err != nil {
-		c.internalErrorf("%#v returned a non-nil result with a non-nil error for %s:\n%v\n%#v", from, req.Method, err, result)
-		result = nil // Discard the spurious result and respond with err.
-	}
-
-	if req.IsCall() {
-		if result == nil && err == nil {
-			err = c.internalErrorf("%#v returned a nil result and nil error for a %q Request that requires a Response", from, req.Method)
-		}
-
-		response, respErr := NewResponse(req.ID, result, err)
-		if debugCall {
-			log.Println("==> processResult", response.ID, string(response.Result), response.Error)
-		}
-
-		// The caller could theoretically reuse the request's ID as soon as we've
-		// sent the response, so ensure that it is removed from the incoming map
-		// before sending.
-		c.updateInFlight(func(s *inFlightState) {
-			delete(s.incomingByID, req.ID)
-		})
-		if respErr == nil {
-			writeErr := c.write(notDone{req.ctx}, response)
-			if err == nil {
-				err = writeErr
-			}
-		} else {
-			err = c.internalErrorf("%#v returned a malformed result for %q: %w", from, req.Method, respErr)
-		}
-	} else { // req is a notification
-		if result != nil {
-			err = c.internalErrorf("%#v returned a non-nil result for a %q Request without an ID", from, req.Method)
-		} else if err != nil {
-			err = fmt.Errorf("%w: %q notification failed: %v", ErrInternal, req.Method, err)
-		}
-	}
-	_ = err
-
-	// Cancel the request and finalize the event span to free any associated resources.
-	req.cancel()
-	c.updateInFlight(func(s *inFlightState) {
-		if s.incoming == 0 {
-			panic("jsonrpc2_v2: processResult called when incoming count is already zero")
-		}
-		s.incoming--
-	})
-	return nil
-}
-
-// write is used by all things that write outgoing messages, including replies.
-// it makes sure that writes are atomic
-func (c *Connection) write(ctx context.Context, msg Message) error {
-	writer := <-c.writer
-	defer func() { c.writer <- writer }()
-	_, err := writer.Write(ctx, msg)
-
-	if err != nil && ctx.Err() == nil {
-		// The call to Write failed, and since ctx.Err() is nil we can't attribute
-		// the failure (even indirectly) to Context cancellation. The writer appears
-		// to be broken, and future writes are likely to also fail.
-		//
-		// If the read side of the connection is also broken, we might not even be
-		// able to receive cancellation notifications. Since we can't reliably write
-		// the results of incoming calls and can't receive explicit cancellations,
-		// cancel the calls now.
-		c.updateInFlight(func(s *inFlightState) {
-			if s.writeErr == nil {
-				s.writeErr = err
-				for _, r := range s.incomingByID {
-					r.cancel()
-				}
-			}
-		})
-	}
-
-	return err
-}
-
-// internalErrorf reports an internal error. By default it panics, but if
-// c.onInternalError is non-nil it instead calls that and returns an error
-// wrapping ErrInternal.
-func (c *Connection) internalErrorf(format string, args ...interface{}) error {
-	err := fmt.Errorf(format, args...)
-	c.onInternalError(err)
-
-	return fmt.Errorf("%w: %v", ErrInternal, err)
-}
-
-// notDone is a context.Context wrapper that returns a nil Done channel.
-type notDone struct{ ctx context.Context }
-
-func (ic notDone) Value(key interface{}) interface{} {
-	return ic.ctx.Value(key)
-}
-
-func (notDone) Done() <-chan struct{}       { return nil }
-func (notDone) Err() error                  { return nil }
-func (notDone) Deadline() (time.Time, bool) { return time.Time{}, false }
diff --git a/x/jsonrpc2/frame.go b/x/jsonrpc2/frame.go
deleted file mode 100644
index 941ef2bc..00000000
--- a/x/jsonrpc2/frame.go
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (c) 2023 The GoPlus Authors (goplus.org). All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// 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.
-
-package jsonrpc2
-
-import (
-	"bufio"
-	"context"
-	"fmt"
-	"io"
-	"strconv"
-	"strings"
-)
-
-// Reader abstracts the transport mechanics from the JSON RPC protocol.
-// A Conn reads messages from the reader it was provided on construction,
-// and assumes that each call to Read fully transfers a single message,
-// or returns an error.
-// A reader is not safe for concurrent use, it is expected it will be used by
-// a single Conn in a safe manner.
-type Reader interface {
-	// Read gets the next message from the stream.
-	Read(context.Context) (Message, int64, error)
-}
-
-// Writer abstracts the transport mechanics from the JSON RPC protocol.
-// A Conn writes messages using the writer it was provided on construction,
-// and assumes that each call to Write fully transfers a single message,
-// or returns an error.
-// A writer is not safe for concurrent use, it is expected it will be used by
-// a single Conn in a safe manner.
-type Writer interface {
-	// Write sends a message to the stream.
-	Write(context.Context, Message) (int64, error)
-}
-
-// Framer wraps low level byte readers and writers into jsonrpc2 message
-// readers and writers.
-// It is responsible for the framing and encoding of messages into wire form.
-type Framer interface {
-	// Reader wraps a byte reader into a message reader.
-	Reader(rw io.Reader) Reader
-	// Writer wraps a byte writer into a message writer.
-	Writer(rw io.Writer) Writer
-}
-
-// HeaderFramer returns a new Framer.
-// The messages are sent with HTTP content length and MIME type headers.
-// This is the format used by LSP and others.
-func HeaderFramer() Framer { return headerFramer{} }
-
-type headerFramer struct{}
-type headerReader struct{ in *bufio.Reader }
-type headerWriter struct{ out io.Writer }
-
-func (headerFramer) Reader(rw io.Reader) Reader {
-	return &headerReader{in: bufio.NewReader(rw)}
-}
-
-func (headerFramer) Writer(rw io.Writer) Writer {
-	return &headerWriter{out: rw}
-}
-
-func (r *headerReader) Read(ctx context.Context) (Message, int64, error) {
-	select {
-	case <-ctx.Done():
-		return nil, 0, ctx.Err()
-	default:
-	}
-	var total, length int64
-	// read the header, stop on the first empty line
-	for {
-		line, err := r.in.ReadString('\n')
-		total += int64(len(line))
-		if err != nil {
-			if err == io.EOF {
-				if total == 0 {
-					return nil, 0, io.EOF
-				}
-				err = io.ErrUnexpectedEOF
-			}
-			return nil, total, fmt.Errorf("failed reading header line: %w", err)
-		}
-		line = strings.TrimSpace(line)
-		// check we have a header line
-		if line == "" {
-			break
-		}
-		colon := strings.IndexRune(line, ':')
-		if colon < 0 {
-			return nil, total, fmt.Errorf("invalid header line %q", line)
-		}
-		name, value := line[:colon], strings.TrimSpace(line[colon+1:])
-		switch name {
-		case "Content-Length":
-			if length, err = strconv.ParseInt(value, 10, 32); err != nil {
-				return nil, total, fmt.Errorf("failed parsing Content-Length: %v", value)
-			}
-			if length <= 0 {
-				return nil, total, fmt.Errorf("invalid Content-Length: %v", length)
-			}
-		default:
-			// ignoring unknown headers
-		}
-	}
-	if length == 0 {
-		return nil, total, fmt.Errorf("missing Content-Length header")
-	}
-	data := make([]byte, length)
-	n, err := io.ReadFull(r.in, data)
-	total += int64(n)
-	if err != nil {
-		return nil, total, err
-	}
-	msg, err := DecodeMessage(data)
-	return msg, total, err
-}
-
-func (w *headerWriter) Write(ctx context.Context, msg Message) (int64, error) {
-	select {
-	case <-ctx.Done():
-		return 0, ctx.Err()
-	default:
-	}
-	data, err := EncodeMessage(msg)
-	if err != nil {
-		return 0, fmt.Errorf("marshaling message: %v", err)
-	}
-	n, err := fmt.Fprintf(w.out, "Content-Length: %v\r\n\r\n", len(data))
-	total := int64(n)
-	if err == nil {
-		n, err = w.out.Write(data)
-		total += int64(n)
-	}
-	return total, err
-}
diff --git a/x/jsonrpc2/internal/stack/parse.go b/x/jsonrpc2/internal/stack/parse.go
deleted file mode 100644
index b7f08d08..00000000
--- a/x/jsonrpc2/internal/stack/parse.go
+++ /dev/null
@@ -1,172 +0,0 @@
-// Copyright 2020 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.
-
-package stack
-
-import (
-	"bufio"
-	"io"
-	"regexp"
-	"strconv"
-)
-
-var (
-	reBlank     = regexp.MustCompile(`^\s*$`)
-	reGoroutine = regexp.MustCompile(`^\s*goroutine (\d+) \[([^\]]*)\]:\s*$`)
-	reCall      = regexp.MustCompile(`^\s*` +
-		`(created by )?` + //marker
-		`(([\w/.]+/)?[\w]+)\.` + //package
-		`(\(([^:.)]*)\)\.)?` + //optional type
-		`([\w\.]+)` + //function
-		`(\(.*\))?` + // args
-		`\s*$`)
-	rePos = regexp.MustCompile(`^\s*(.*):(\d+)( .*)?$`)
-)
-
-// Scanner splits an input stream into lines in a way that is consumable by
-// the parser.
-type Scanner struct {
-	lines *bufio.Scanner
-	done  bool
-}
-
-// NewScanner creates a scanner on top of a reader.
-func NewScanner(r io.Reader) *Scanner {
-	s := &Scanner{
-		lines: bufio.NewScanner(r),
-	}
-	s.Skip() // prefill
-	return s
-}
-
-// Peek returns the next line without consuming it.
-func (s *Scanner) Peek() string {
-	if s.done {
-		return ""
-	}
-	return s.lines.Text()
-}
-
-// Skip consumes the next line without looking at it.
-// Normally used after it has already been looked at using Peek.
-func (s *Scanner) Skip() {
-	if !s.lines.Scan() {
-		s.done = true
-	}
-}
-
-// Next consumes and returns the next line.
-func (s *Scanner) Next() string {
-	line := s.Peek()
-	s.Skip()
-	return line
-}
-
-// Done returns true if the scanner has reached the end of the underlying
-// stream.
-func (s *Scanner) Done() bool {
-	return s.done
-}
-
-// Err returns true if the scanner has reached the end of the underlying
-// stream.
-func (s *Scanner) Err() error {
-	return s.lines.Err()
-}
-
-// Match returns the submatchs of the regular expression against the next line.
-// If it matched the line is also consumed.
-func (s *Scanner) Match(re *regexp.Regexp) []string {
-	if s.done {
-		return nil
-	}
-	match := re.FindStringSubmatch(s.Peek())
-	if match != nil {
-		s.Skip()
-	}
-	return match
-}
-
-// SkipBlank skips any number of pure whitespace lines.
-func (s *Scanner) SkipBlank() {
-	for !s.done {
-		line := s.Peek()
-		if len(line) != 0 && !reBlank.MatchString(line) {
-			return
-		}
-		s.Skip()
-	}
-}
-
-// Parse the current contiguous block of goroutine stack traces until the
-// scanned content no longer matches.
-func Parse(scanner *Scanner) (Dump, error) {
-	dump := Dump{}
-	for {
-		gr, ok := parseGoroutine(scanner)
-		if !ok {
-			return dump, nil
-		}
-		dump = append(dump, gr)
-	}
-}
-
-func parseGoroutine(scanner *Scanner) (Goroutine, bool) {
-	match := scanner.Match(reGoroutine)
-	if match == nil {
-		return Goroutine{}, false
-	}
-	id, _ := strconv.ParseInt(match[1], 0, 32)
-	gr := Goroutine{
-		ID:    int(id),
-		State: match[2],
-	}
-	for {
-		frame, ok := parseFrame(scanner)
-		if !ok {
-			scanner.SkipBlank()
-			return gr, true
-		}
-		if frame.Position.Filename != "" {
-			gr.Stack = append(gr.Stack, frame)
-		}
-	}
-}
-
-func parseFrame(scanner *Scanner) (Frame, bool) {
-	fun, ok := parseFunction(scanner)
-	if !ok {
-		return Frame{}, false
-	}
-	frame := Frame{
-		Function: fun,
-	}
-	frame.Position, ok = parsePosition(scanner)
-	// if ok is false, then this is a broken state.
-	// we got the func but not the file that must follow
-	// the consumed line can be recovered from the frame
-	//TODO: push back the fun raw
-	return frame, ok
-}
-
-func parseFunction(scanner *Scanner) (Function, bool) {
-	match := scanner.Match(reCall)
-	if match == nil {
-		return Function{}, false
-	}
-	return Function{
-		Package: match[2],
-		Type:    match[5],
-		Name:    match[6],
-	}, true
-}
-
-func parsePosition(scanner *Scanner) (Position, bool) {
-	match := scanner.Match(rePos)
-	if match == nil {
-		return Position{}, false
-	}
-	line, _ := strconv.ParseInt(match[2], 0, 32)
-	return Position{Filename: match[1], Line: int(line)}, true
-}
diff --git a/x/jsonrpc2/internal/stack/process.go b/x/jsonrpc2/internal/stack/process.go
deleted file mode 100644
index 8812de95..00000000
--- a/x/jsonrpc2/internal/stack/process.go
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright 2020 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.
-
-package stack
-
-import (
-	"bytes"
-	"fmt"
-	"io"
-	"runtime"
-	"sort"
-)
-
-// Capture get the current stack traces from the runtime.
-func Capture() Dump {
-	buf := make([]byte, 2<<20)
-	buf = buf[:runtime.Stack(buf, true)]
-	scanner := NewScanner(bytes.NewReader(buf))
-	dump, _ := Parse(scanner)
-	return dump
-}
-
-// Summarize a dump for easier consumption.
-// This collates goroutines with equivalent stacks.
-func Summarize(dump Dump) Summary {
-	s := Summary{
-		Total: len(dump),
-	}
-	for _, gr := range dump {
-		s.addGoroutine(gr)
-	}
-	return s
-}
-
-// Process and input stream to an output stream, summarizing any stacks that
-// are detected in place.
-func Process(out io.Writer, in io.Reader) error {
-	scanner := NewScanner(in)
-	for {
-		dump, err := Parse(scanner)
-		summary := Summarize(dump)
-		switch {
-		case len(dump) > 0:
-			fmt.Fprintf(out, "%+v\n\n", summary)
-		case err != nil:
-			return err
-		case scanner.Done():
-			return scanner.Err()
-		default:
-			// must have been a line that is not part of a dump
-			fmt.Fprintln(out, scanner.Next())
-		}
-	}
-}
-
-// Diff calculates the delta between two dumps.
-func Diff(before, after Dump) Delta {
-	result := Delta{}
-	processed := make(map[int]bool)
-	for _, gr := range before {
-		processed[gr.ID] = false
-	}
-	for _, gr := range after {
-		if _, found := processed[gr.ID]; found {
-			result.Shared = append(result.Shared, gr)
-		} else {
-			result.After = append(result.After, gr)
-		}
-		processed[gr.ID] = true
-	}
-	for _, gr := range before {
-		if done := processed[gr.ID]; !done {
-			result.Before = append(result.Before, gr)
-		}
-	}
-	return result
-}
-
-// TODO: do we want to allow contraction of stacks before comparison?
-func (s *Summary) addGoroutine(gr Goroutine) {
-	index := sort.Search(len(s.Calls), func(i int) bool {
-		return !s.Calls[i].Stack.less(gr.Stack)
-	})
-	if index >= len(s.Calls) || !s.Calls[index].Stack.equal(gr.Stack) {
-		// insert new stack, first increase the length
-		s.Calls = append(s.Calls, Call{})
-		// move the top part upward to make space
-		copy(s.Calls[index+1:], s.Calls[index:])
-		// insert the new call
-		s.Calls[index] = Call{
-			Stack: gr.Stack,
-		}
-	}
-	// merge the goroutine into the matched call
-	s.Calls[index].merge(gr)
-}
-
-// TODO: do we want other grouping strategies?
-func (c *Call) merge(gr Goroutine) {
-	for i := range c.Groups {
-		canditate := &c.Groups[i]
-		if canditate.State == gr.State {
-			canditate.Goroutines = append(canditate.Goroutines, gr)
-			return
-		}
-	}
-	c.Groups = append(c.Groups, Group{
-		State:      gr.State,
-		Goroutines: []Goroutine{gr},
-	})
-}
diff --git a/x/jsonrpc2/internal/stack/stack.go b/x/jsonrpc2/internal/stack/stack.go
deleted file mode 100644
index 479301a7..00000000
--- a/x/jsonrpc2/internal/stack/stack.go
+++ /dev/null
@@ -1,170 +0,0 @@
-// Copyright 2020 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.
-
-// Package stack provides support for parsing standard goroutine stack traces.
-package stack
-
-import (
-	"fmt"
-	"text/tabwriter"
-)
-
-// Dump is a raw set of goroutines and their stacks.
-type Dump []Goroutine
-
-// Goroutine is a single parsed goroutine dump.
-type Goroutine struct {
-	State string // state that the goroutine is in.
-	ID    int    // id of the goroutine.
-	Stack Stack  // call frames that make up the stack
-}
-
-// Stack is a set of frames in a callstack.
-type Stack []Frame
-
-// Frame is a point in a call stack.
-type Frame struct {
-	Function Function
-	Position Position
-}
-
-// Function is the function called at a frame.
-type Function struct {
-	Package string // package name of function if known
-	Type    string // if set function is a method of this type
-	Name    string // function name of the frame
-}
-
-// Position is the file position for a frame.
-type Position struct {
-	Filename string // source filename
-	Line     int    // line number within file
-}
-
-// Summary is a set of stacks processed and collated into Calls.
-type Summary struct {
-	Total int    // the total count of goroutines in the summary
-	Calls []Call // the collated stack traces
-}
-
-// Call is set of goroutines that all share the same callstack.
-// They will be grouped by state.
-type Call struct {
-	Stack  Stack   // the shared callstack information
-	Groups []Group // the sets of goroutines with the same state
-}
-
-// Group is a set of goroutines with the same stack that are in the same state.
-type Group struct {
-	State      string      // the shared state of the goroutines
-	Goroutines []Goroutine // the set of goroutines in this group
-}
-
-// Delta represents the difference between two stack dumps.
-type Delta struct {
-	Before Dump // The goroutines that were only in the before set.
-	Shared Dump // The goroutines that were in both sets.
-	After  Dump // The goroutines that were only in the after set.
-}
-
-func (s Stack) equal(other Stack) bool {
-	if len(s) != len(other) {
-		return false
-	}
-	for i, frame := range s {
-		if !frame.equal(other[i]) {
-			return false
-		}
-	}
-	return true
-}
-
-func (s Stack) less(other Stack) bool {
-	for i, frame := range s {
-		if i >= len(other) {
-			return false
-		}
-		if frame.less(other[i]) {
-			return true
-		}
-		if !frame.equal(other[i]) {
-			return false
-		}
-	}
-	return len(s) < len(other)
-}
-
-func (f Frame) equal(other Frame) bool {
-	return f.Position.equal(other.Position)
-}
-
-func (f Frame) less(other Frame) bool {
-	return f.Position.less(other.Position)
-}
-
-func (p Position) equal(other Position) bool {
-	return p.Filename == other.Filename && p.Line == other.Line
-}
-
-func (p Position) less(other Position) bool {
-	if p.Filename < other.Filename {
-		return true
-	}
-	if p.Filename > other.Filename {
-		return false
-	}
-	return p.Line < other.Line
-}
-
-func (s Summary) Format(w fmt.State, r rune) {
-	tw := tabwriter.NewWriter(w, 0, 0, 1, ' ', 0)
-	for i, c := range s.Calls {
-		if i > 0 {
-			fmt.Fprintf(tw, "\n\n")
-			tw.Flush()
-		}
-		fmt.Fprint(tw, c)
-	}
-	tw.Flush()
-	if s.Total > 0 && w.Flag('+') {
-		fmt.Fprintf(w, "\n\n%d goroutines, %d unique", s.Total, len(s.Calls))
-	}
-}
-
-func (c Call) Format(w fmt.State, r rune) {
-	for i, g := range c.Groups {
-		if i > 0 {
-			fmt.Fprint(w, " ")
-		}
-		fmt.Fprint(w, g)
-	}
-	for _, f := range c.Stack {
-		fmt.Fprintf(w, "\n%v", f)
-	}
-}
-
-func (g Group) Format(w fmt.State, r rune) {
-	fmt.Fprintf(w, "[%v]: ", g.State)
-	for i, gr := range g.Goroutines {
-		if i > 0 {
-			fmt.Fprint(w, ", ")
-		}
-		fmt.Fprintf(w, "$%d", gr.ID)
-	}
-}
-
-func (f Frame) Format(w fmt.State, c rune) {
-	fmt.Fprintf(w, "%v:\t%v", f.Position, f.Function)
-}
-
-func (f Function) Format(w fmt.State, c rune) {
-	if f.Type != "" {
-		fmt.Fprintf(w, "(%v).", f.Type)
-	}
-	fmt.Fprintf(w, "%v", f.Name)
-}
-
-func (p Position) Format(w fmt.State, c rune) {
-	fmt.Fprintf(w, "%v:%v", p.Filename, p.Line)
-}
diff --git a/x/jsonrpc2/jsonrpc2.go b/x/jsonrpc2/jsonrpc2.go
deleted file mode 100644
index 8c758389..00000000
--- a/x/jsonrpc2/jsonrpc2.go
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (c) 2023 The GoPlus Authors (goplus.org). All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// 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.
-
-// Package jsonrpc2 is a minimal implementation of the JSON RPC 2 spec.
-// https://www.jsonrpc.org/specification
-// It is intended to be compatible with other implementations at the wire level.
-package jsonrpc2
-
-import (
-	"context"
-	"errors"
-)
-
-type dbgFlags int
-
-const (
-	DbgFlagVerbose dbgFlags = 1 << iota
-	DbgFlagCall
-	DbgFlagAll = DbgFlagVerbose | DbgFlagCall
-)
-
-var (
-	Verbose   bool
-	debugCall bool
-)
-
-// SetDebug sets debug flags.
-func SetDebug(flags dbgFlags) {
-	Verbose = (flags & DbgFlagVerbose) != 0
-	debugCall = (flags & (DbgFlagCall | DbgFlagVerbose)) != 0
-}
-
-var (
-	// ErrIdleTimeout is returned when serving timed out waiting for new connections.
-	ErrIdleTimeout = errors.New("timed out waiting for new connections")
-
-	// ErrNotHandled is returned from a Handler or Preempter to indicate it did
-	// not handle the request.
-	//
-	// If a Handler returns ErrNotHandled, the server replies with
-	// ErrMethodNotFound.
-	ErrNotHandled = errors.New("JSON RPC not handled")
-
-	// ErrAsyncResponse is returned from a handler to indicate it will generate a
-	// response asynchronously.
-	//
-	// ErrAsyncResponse must not be returned for notifications,
-	// which do not receive responses.
-	ErrAsyncResponse = errors.New("JSON RPC asynchronous response")
-)
-
-// Preempter handles messages on a connection before they are queued to the main
-// handler.
-// Primarily this is used for cancel handlers or notifications for which out of
-// order processing is not an issue.
-type Preempter interface {
-	// Preempt is invoked for each incoming request before it is queued for handling.
-	//
-	// If Preempt returns ErrNotHandled, the request will be queued,
-	// and eventually passed to a Handle call.
-	//
-	// Otherwise, the result and error are processed as if returned by Handle.
-	//
-	// Preempt must not block. (The Context passed to it is for Values only.)
-	Preempt(ctx context.Context, req *Request) (result interface{}, err error)
-}
-
-// A PreempterFunc implements the Preempter interface for a standalone Preempt function.
-type PreempterFunc func(ctx context.Context, req *Request) (interface{}, error)
-
-func (f PreempterFunc) Preempt(ctx context.Context, req *Request) (interface{}, error) {
-	return f(ctx, req)
-}
-
-var _ Preempter = PreempterFunc(nil)
-
-// Handler handles messages on a connection.
-type Handler interface {
-	// Handle is invoked sequentially for each incoming request that has not
-	// already been handled by a Preempter.
-	//
-	// If the Request has a nil ID, Handle must return a nil result,
-	// and any error may be logged but will not be reported to the caller.
-	//
-	// If the Request has a non-nil ID, Handle must return either a
-	// non-nil, JSON-marshalable result, or a non-nil error.
-	//
-	// The Context passed to Handle will be canceled if the
-	// connection is broken or the request is canceled or completed.
-	// (If Handle returns ErrAsyncResponse, ctx will remain uncanceled
-	// until either Cancel or Respond is called for the request's ID.)
-	Handle(ctx context.Context, req *Request) (result interface{}, err error)
-}
-
-type defaultHandler struct{}
-
-func (defaultHandler) Preempt(context.Context, *Request) (interface{}, error) {
-	return nil, ErrNotHandled
-}
-
-func (defaultHandler) Handle(context.Context, *Request) (interface{}, error) {
-	return nil, ErrNotHandled
-}
-
-// A HandlerFunc implements the Handler interface for a standalone Handle function.
-type HandlerFunc func(ctx context.Context, req *Request) (interface{}, error)
-
-func (f HandlerFunc) Handle(ctx context.Context, req *Request) (interface{}, error) {
-	return f(ctx, req)
-}
-
-var _ Handler = HandlerFunc(nil)
-
-func defaultHandleError(err error) {
-	panic("jsonrpc2: " + err.Error())
-}
-
-// async is a small helper for operations with an asynchronous result that you
-// can wait for.
-type async struct {
-	ready    chan struct{} // closed when done
-	firstErr chan error    // 1-buffered; contains either nil or the first non-nil error
-}
-
-func newAsync() *async {
-	var a async
-	a.ready = make(chan struct{})
-	a.firstErr = make(chan error, 1)
-	a.firstErr <- nil
-	return &a
-}
-
-func (a *async) done() {
-	close(a.ready)
-}
-
-func (a *async) wait() error {
-	<-a.ready
-	err := <-a.firstErr
-	a.firstErr <- err
-	return err
-}
-
-func (a *async) setError(err error) {
-	storedErr := <-a.firstErr
-	if storedErr == nil {
-		storedErr = err
-	}
-	a.firstErr <- storedErr
-}
diff --git a/x/jsonrpc2/messages.go b/x/jsonrpc2/messages.go
deleted file mode 100644
index 509f607b..00000000
--- a/x/jsonrpc2/messages.go
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright (c) 2023 The GoPlus Authors (goplus.org). All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// 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.
-
-package jsonrpc2
-
-import (
-	"encoding/json"
-	"errors"
-	"fmt"
-)
-
-// ID is a Request identifier.
-type ID struct {
-	value interface{}
-}
-
-// Message is the interface to all jsonrpc2 message types.
-// They share no common functionality, but are a closed set of concrete types
-// that are allowed to implement this interface. The message types are *Request
-// and *Response.
-type Message interface {
-	// marshal builds the wire form from the API form.
-	// It is private, which makes the set of Message implementations closed.
-	marshal(to *wireCombined)
-}
-
-// Request is a Message sent to a peer to request behavior.
-// If it has an ID it is a call, otherwise it is a notification.
-type Request struct {
-	// ID of this request, used to tie the Response back to the request.
-	// This will be nil for notifications.
-	ID ID
-	// Method is a string containing the method name to invoke.
-	Method string
-	// Params is either a struct or an array with the parameters of the method.
-	Params json.RawMessage
-}
-
-// Response is a Message used as a reply to a call Request.
-// It will have the same ID as the call it is a response to.
-type Response struct {
-	// result is the content of the response.
-	Result json.RawMessage
-	// err is set only if the call failed.
-	Error error
-	// id of the request this is a response to.
-	ID ID
-}
-
-// StringID creates a new string request identifier.
-func StringID(s string) ID { return ID{value: s} }
-
-// Int64ID creates a new integer request identifier.
-func Int64ID(i int64) ID { return ID{value: i} }
-
-// IsValid returns true if the ID is a valid identifier.
-// The default value for ID will return false.
-func (id ID) IsValid() bool { return id.value != nil }
-
-// Raw returns the underlying value of the ID.
-func (id ID) Raw() interface{} { return id.value }
-
-// NewNotification constructs a new Notification message for the supplied
-// method and parameters.
-func NewNotification(method string, params interface{}) (*Request, error) {
-	p, merr := marshalToRaw(params)
-	return &Request{Method: method, Params: p}, merr
-}
-
-// NewCall constructs a new Call message for the supplied ID, method and
-// parameters.
-func NewCall(id ID, method string, params interface{}) (*Request, error) {
-	p, merr := marshalToRaw(params)
-	return &Request{ID: id, Method: method, Params: p}, merr
-}
-
-func (msg *Request) IsCall() bool { return msg.ID.IsValid() }
-
-func (msg *Request) marshal(to *wireCombined) {
-	to.ID = msg.ID.value
-	to.Method = msg.Method
-	to.Params = msg.Params
-}
-
-// NewResponse constructs a new Response message that is a reply to the
-// supplied. If err is set result may be ignored.
-func NewResponse(id ID, result interface{}, rerr error) (*Response, error) {
-	r, merr := marshalToRaw(result)
-	return &Response{ID: id, Result: r, Error: rerr}, merr
-}
-
-func (msg *Response) marshal(to *wireCombined) {
-	to.ID = msg.ID.value
-	to.Error = toWireError(msg.Error)
-	to.Result = msg.Result
-}
-
-func toWireError(err error) *wireError {
-	if err == nil {
-		// no error, the response is complete
-		return nil
-	}
-	if err, ok := err.(*wireError); ok {
-		// already a wire error, just use it
-		return err
-	}
-	result := &wireError{Message: err.Error()}
-	var wrapped *wireError
-	if errors.As(err, &wrapped) {
-		// if we wrapped a wire error, keep the code from the wrapped error
-		// but the message from the outer error
-		result.Code = wrapped.Code
-	}
-	return result
-}
-
-func EncodeMessage(msg Message) ([]byte, error) {
-	wire := wireCombined{VersionTag: wireVersion}
-	msg.marshal(&wire)
-	data, err := json.Marshal(&wire)
-	if err != nil {
-		return data, fmt.Errorf("marshaling jsonrpc message: %w", err)
-	}
-	return data, nil
-}
-
-func DecodeMessage(data []byte) (Message, error) {
-	msg := wireCombined{}
-	if err := json.Unmarshal(data, &msg); err != nil {
-		return nil, fmt.Errorf("unmarshaling jsonrpc message: %w", err)
-	}
-	if msg.VersionTag != wireVersion {
-		return nil, fmt.Errorf("invalid message version tag %s expected %s", msg.VersionTag, wireVersion)
-	}
-	id := ID{}
-	switch v := msg.ID.(type) {
-	case nil:
-	case float64:
-		// coerce the id type to int64 if it is float64, the spec does not allow fractional parts
-		id = Int64ID(int64(v))
-	case int64:
-		id = Int64ID(v)
-	case string:
-		id = StringID(v)
-	default:
-		return nil, fmt.Errorf("invalid message id type <%T>%v", v, v)
-	}
-	if msg.Method != "" {
-		// has a method, must be a call
-		return &Request{
-			Method: msg.Method,
-			ID:     id,
-			Params: msg.Params,
-		}, nil
-	}
-	// no method, should be a response
-	if !id.IsValid() {
-		return nil, ErrInvalidRequest
-	}
-	resp := &Response{
-		ID:     id,
-		Result: msg.Result,
-	}
-	// we have to check if msg.Error is nil to avoid a typed error
-	if msg.Error != nil {
-		resp.Error = msg.Error
-	}
-	return resp, nil
-}
-
-func marshalToRaw(obj interface{}) (json.RawMessage, error) {
-	if obj == nil {
-		return nil, nil
-	}
-	data, err := json.Marshal(obj)
-	if err != nil {
-		return nil, err
-	}
-	return json.RawMessage(data), nil
-}
diff --git a/x/jsonrpc2/serve.go b/x/jsonrpc2/serve.go
deleted file mode 100644
index 95ce0744..00000000
--- a/x/jsonrpc2/serve.go
+++ /dev/null
@@ -1,354 +0,0 @@
-/*
- * Copyright (c) 2023 The GoPlus Authors (goplus.org). All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// Copyright 2020 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.
-
-package jsonrpc2
-
-import (
-	"context"
-	"fmt"
-	"io"
-	"log"
-	"runtime"
-	"sync"
-	"sync/atomic"
-	"time"
-)
-
-// Listener is implemented by protocols to accept new inbound connections.
-type Listener interface {
-	// Accept accepts an inbound connection to a server.
-	// It blocks until either an inbound connection is made, or the listener is closed.
-	Accept(context.Context) (io.ReadWriteCloser, error)
-
-	// Close closes the listener.
-	// Any blocked Accept or Dial operations will unblock and return errors.
-	Close() error
-
-	// Dialer returns a dialer that can be used to connect to this listener
-	// locally.
-	// If a listener does not implement this it will return nil.
-	Dialer() Dialer
-}
-
-// Dialer is used by clients to dial a server.
-type Dialer interface {
-	// Dial returns a new communication byte stream to a listening server.
-	Dial(ctx context.Context) (io.ReadWriteCloser, error)
-}
-
-// Server is a running server that is accepting incoming connections.
-type Server struct {
-	listener Listener
-	binder   Binder
-	async    *async
-
-	shutdownOnce sync.Once
-	closing      int32 // atomic: set to nonzero when Shutdown is called
-}
-
-// Dial uses the dialer to make a new connection, wraps the returned
-// reader and writer using the framer to make a stream, and then builds
-// a connection on top of that stream using the binder.
-//
-// The returned Connection will operate independently using the Preempter and/or
-// Handler provided by the Binder, and will release its own resources when the
-// connection is broken, but the caller may Close it earlier to stop accepting
-// (or sending) new requests.
-func Dial(ctx context.Context, dialer Dialer, binder Binder) (*Connection, error) {
-	// dial a server
-	rwc, err := dialer.Dial(ctx)
-	if err != nil {
-		return nil, err
-	}
-	return newConnection(ctx, rwc, binder, nil), nil
-}
-
-// NewServer starts a new server listening for incoming connections and returns
-// it.
-// This returns a fully running and connected server, it does not block on
-// the listener.
-// You can call Wait to block on the server, or Shutdown to get the sever to
-// terminate gracefully.
-// To notice incoming connections, use an intercepting Binder.
-func NewServer(ctx context.Context, listener Listener, binder Binder) *Server {
-	server := &Server{
-		listener: listener,
-		binder:   binder,
-		async:    newAsync(),
-	}
-	go server.run(ctx)
-	return server
-}
-
-// Wait returns only when the server has shut down.
-func (s *Server) Wait() (err error) {
-	if Verbose {
-		log.Println("==> Server.Wait start")
-	}
-	err = s.async.wait()
-	if Verbose {
-		log.Println("==> Server.Wait end:", err)
-	}
-	return
-}
-
-// Shutdown informs the server to stop accepting new connections.
-func (s *Server) Shutdown() {
-	s.shutdownOnce.Do(func() {
-		atomic.StoreInt32(&s.closing, 1)
-		s.listener.Close()
-	})
-}
-
-// run accepts incoming connections from the listener,
-// If IdleTimeout is non-zero, run exits after there are no clients for this
-// duration, otherwise it exits only on error.
-func (s *Server) run(ctx context.Context) {
-	defer s.async.done()
-
-	var activeConns sync.WaitGroup
-	for {
-		rwc, err := s.listener.Accept(ctx)
-		if err != nil {
-			// Only Shutdown closes the listener. If we get an error after Shutdown is
-			// called, assume that was the cause and don't report the error;
-			// otherwise, report the error in case it is unexpected.
-			if atomic.LoadInt32(&s.closing) == 0 {
-				s.async.setError(err)
-			}
-			// We are done generating new connections for good.
-			break
-		}
-
-		// A new inbound connection.
-		activeConns.Add(1)
-		_ = newConnection(ctx, rwc, s.binder, activeConns.Done) // unregisters itself when done
-	}
-	activeConns.Wait()
-}
-
-// NewIdleListener wraps a listener with an idle timeout.
-//
-// When there are no active connections for at least the timeout duration,
-// calls to Accept will fail with ErrIdleTimeout.
-//
-// A connection is considered inactive as soon as its Close method is called.
-func NewIdleListener(timeout time.Duration, wrap Listener) Listener {
-	l := &idleListener{
-		wrapped:   wrap,
-		timeout:   timeout,
-		active:    make(chan int, 1),
-		timedOut:  make(chan struct{}),
-		idleTimer: make(chan *time.Timer, 1),
-	}
-	l.idleTimer <- time.AfterFunc(l.timeout, l.timerExpired)
-	return l
-}
-
-type idleListener struct {
-	wrapped Listener
-	timeout time.Duration
-
-	// Only one of these channels is receivable at any given time.
-	active    chan int         // count of active connections; closed when Close is called if not timed out
-	timedOut  chan struct{}    // closed when the idle timer expires
-	idleTimer chan *time.Timer // holds the timer only when idle
-}
-
-// Accept accepts an incoming connection.
-//
-// If an incoming connection is accepted concurrent to the listener being closed
-// due to idleness, the new connection is immediately closed.
-func (l *idleListener) Accept(ctx context.Context) (io.ReadWriteCloser, error) {
-	rwc, err := l.wrapped.Accept(ctx)
-
-	select {
-	case n, ok := <-l.active:
-		if err != nil {
-			if ok {
-				l.active <- n
-			}
-			return nil, err
-		}
-		if ok {
-			l.active <- n + 1
-		} else {
-			// l.wrapped.Close Close has been called, but Accept returned a
-			// connection. This race can occur with concurrent Accept and Close calls
-			// with any net.Listener, and it is benign: since the listener was closed
-			// explicitly, it can't have also timed out.
-			_ = 0
-		}
-		return l.newConn(rwc), nil
-
-	case <-l.timedOut:
-		if err == nil {
-			// Keeping the connection open would leave the listener simultaneously
-			// active and closed due to idleness, which would be contradictory and
-			// confusing. Close the connection and pretend that it never happened.
-			rwc.Close()
-		} else {
-			// In theory the timeout could have raced with an unrelated error return
-			// from Accept. However, ErrIdleTimeout is arguably still valid (since we
-			// would have closed due to the timeout independent of the error), and the
-			// harm from returning a spurious ErrIdleTimeout is negligible anyway.
-			_ = 0
-		}
-		return nil, ErrIdleTimeout
-
-	case timer := <-l.idleTimer:
-		if err != nil {
-			// The idle timer doesn't run until it receives itself from the idleTimer
-			// channel, so it can't have called l.wrapped.Close yet and thus err can't
-			// be ErrIdleTimeout. Leave the idle timer as it was and return whatever
-			// error we got.
-			l.idleTimer <- timer
-			return nil, err
-		}
-
-		if !timer.Stop() {
-			// Failed to stop the timer — the timer goroutine is in the process of
-			// firing. Send the timer back to the timer goroutine so that it can
-			// safely close the timedOut channel, and then wait for the listener to
-			// actually be closed before we return ErrIdleTimeout.
-			l.idleTimer <- timer
-			rwc.Close()
-			<-l.timedOut
-			return nil, ErrIdleTimeout
-		}
-
-		l.active <- 1
-		return l.newConn(rwc), nil
-	}
-}
-
-func (l *idleListener) Close() error {
-	select {
-	case _, ok := <-l.active:
-		if ok {
-			close(l.active)
-		}
-
-	case <-l.timedOut:
-		// Already closed by the timer; take care not to double-close if the caller
-		// only explicitly invokes this Close method once, since the io.Closer
-		// interface explicitly leaves doubled Close calls undefined.
-		return ErrIdleTimeout
-
-	case timer := <-l.idleTimer:
-		if !timer.Stop() {
-			// Couldn't stop the timer. It shouldn't take long to run, so just wait
-			// (so that the Listener is guaranteed to be closed before we return)
-			// and pretend that this call happened afterward.
-			// That way we won't leak any timers or goroutines when Close returns.
-			l.idleTimer <- timer
-			<-l.timedOut
-			return ErrIdleTimeout
-		}
-		close(l.active)
-	}
-
-	return l.wrapped.Close()
-}
-
-func (l *idleListener) Dialer() Dialer {
-	return l.wrapped.Dialer()
-}
-
-func (l *idleListener) timerExpired() {
-	select {
-	case n, ok := <-l.active:
-		if ok {
-			panic(fmt.Sprintf("jsonrpc2: idleListener idle timer fired with %d connections still active", n))
-		} else {
-			panic("jsonrpc2: Close finished with idle timer still running")
-		}
-
-	case <-l.timedOut:
-		panic("jsonrpc2: idleListener idle timer fired more than once")
-
-	case <-l.idleTimer:
-		// The timer for this very call!
-	}
-
-	// Close the Listener with all channels still blocked to ensure that this call
-	// to l.wrapped.Close doesn't race with the one in l.Close.
-	defer close(l.timedOut)
-	l.wrapped.Close()
-}
-
-func (l *idleListener) connClosed() {
-	select {
-	case n, ok := <-l.active:
-		if !ok {
-			// l is already closed, so it can't close due to idleness,
-			// and we don't need to track the number of active connections any more.
-			return
-		}
-		n--
-		if n == 0 {
-			l.idleTimer <- time.AfterFunc(l.timeout, l.timerExpired)
-		} else {
-			l.active <- n
-		}
-
-	case <-l.timedOut:
-		panic("jsonrpc2: idleListener idle timer fired before last active connection was closed")
-
-	case <-l.idleTimer:
-		panic("jsonrpc2: idleListener idle timer active before last active connection was closed")
-	}
-}
-
-type idleListenerConn struct {
-	wrapped   io.ReadWriteCloser
-	l         *idleListener
-	closeOnce sync.Once
-}
-
-func (l *idleListener) newConn(rwc io.ReadWriteCloser) *idleListenerConn {
-	c := &idleListenerConn{
-		wrapped: rwc,
-		l:       l,
-	}
-
-	// A caller that forgets to call Close may disrupt the idleListener's
-	// accounting, even though the file descriptor for the underlying connection
-	// may eventually be garbage-collected anyway.
-	//
-	// Set a (best-effort) finalizer to verify that a Close call always occurs.
-	// (We will clear the finalizer explicitly in Close.)
-	runtime.SetFinalizer(c, func(c *idleListenerConn) {
-		panic("jsonrpc2: IdleListener connection became unreachable without a call to Close")
-	})
-
-	return c
-}
-
-func (c *idleListenerConn) Read(p []byte) (int, error)  { return c.wrapped.Read(p) }
-func (c *idleListenerConn) Write(p []byte) (int, error) { return c.wrapped.Write(p) }
-
-func (c *idleListenerConn) Close() error {
-	defer c.closeOnce.Do(func() {
-		c.l.connClosed()
-		runtime.SetFinalizer(c, nil)
-	})
-	return c.wrapped.Close()
-}
diff --git a/x/jsonrpc2/stdio/stdio.go b/x/jsonrpc2/stdio/stdio.go
deleted file mode 100644
index c1f2c6e5..00000000
--- a/x/jsonrpc2/stdio/stdio.go
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright (c) 2023 The GoPlus Authors (goplus.org). All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package stdio
-
-import (
-	"context"
-	"errors"
-	"io"
-	"log"
-	"net"
-	"os"
-	"sync/atomic"
-	"time"
-
-	"github.com/goplus/gop/x/jsonrpc2"
-)
-
-// -----------------------------------------------------------------------------
-
-var (
-	ErrTooManyConnections = errors.New("too many connections")
-)
-
-var (
-	connCnt int32
-)
-
-type conn struct {
-	closed bool
-}
-
-func (p *conn) Read(b []byte) (n int, err error) {
-	if p.closed {
-		return 0, net.ErrClosed
-	}
-	n, err = os.Stdin.Read(b)
-	for n == 0 { // retry (to support localDailer)
-		time.Sleep(time.Millisecond)
-		n, err = os.Stdin.Read(b)
-	}
-	return
-}
-
-func (p *conn) Write(b []byte) (n int, err error) {
-	if p.closed {
-		return 0, net.ErrClosed
-	}
-	return os.Stdout.Write(b)
-}
-
-func (p *conn) Close() error {
-	if jsonrpc2.Verbose {
-		log.Println("==> stdio.conn.Close")
-	}
-	if p.closed {
-		return net.ErrClosed
-	}
-	p.closed = true
-	atomic.AddInt32(&connCnt, -1)
-	return nil
-}
-
-// Dial returns a new communication byte stream to a listening server.
-func (p *conn) Dial(ctx context.Context) (io.ReadWriteCloser, error) {
-	if atomic.AddInt32(&connCnt, 1) != 1 {
-		atomic.AddInt32(&connCnt, -1)
-		return nil, ErrTooManyConnections
-	}
-	return p, nil
-}
-
-// -----------------------------------------------------------------------------
-
-type newConn struct {
-	in, out *os.File
-	r, w    *os.File
-	oStdin  *os.File
-	oStdout *os.File
-	closed  bool
-}
-
-func (p *newConn) Read(b []byte) (n int, err error) {
-	if p.closed {
-		return 0, net.ErrClosed
-	}
-	return p.in.Read(b)
-}
-
-func (p *newConn) Write(b []byte) (n int, err error) {
-	if p.closed {
-		return 0, net.ErrClosed
-	}
-	return p.out.Write(b)
-}
-
-func (p *newConn) Close() error {
-	if jsonrpc2.Verbose {
-		log.Println("==> stdio.newConn.Close")
-	}
-	if p.closed {
-		return net.ErrClosed
-	}
-	p.closed = true
-	atomic.AddInt32(&dailCnt, -1)
-	os.Stdin, os.Stdout = p.oStdin, p.oStdout
-	p.in.Close()
-	p.w.Close()
-	p.r.Close()
-	p.out.Close()
-	return nil
-}
-
-// -----------------------------------------------------------------------------
-
-type listener struct {
-	closed    bool
-	localDail bool
-}
-
-func (p *listener) Close() error {
-	if jsonrpc2.Verbose {
-		log.Println("==> stdio.listener.Close")
-	}
-	if p.closed {
-		return net.ErrClosed
-	}
-	p.closed = true
-	return nil
-}
-
-// Accept blocks waiting for an incoming connection to the listener.
-func (p *listener) Accept(context.Context) (io.ReadWriteCloser, error) {
-	if atomic.AddInt32(&connCnt, 1) != 1 {
-		atomic.AddInt32(&connCnt, -1)
-		return nil, ErrTooManyConnections
-	}
-	return new(conn), nil
-}
-
-var (
-	dailCnt int32
-)
-
-// Dial returns a new communication byte stream to a listening server.
-func (p *listener) Dial(ctx context.Context) (ret io.ReadWriteCloser, err error) {
-	if atomic.AddInt32(&dailCnt, 1) != 1 {
-		atomic.AddInt32(&dailCnt, -1)
-		return nil, ErrTooManyConnections
-	}
-	in, w, err := os.Pipe()
-	if err != nil {
-		return
-	}
-	r, out, err := os.Pipe()
-	if err != nil {
-		in.Close()
-		w.Close()
-		return
-	}
-	oStdin, oStdout := os.Stdin, os.Stdout
-	os.Stdin, os.Stdout = r, w
-	return &newConn{in: in, out: out, r: r, w: w, oStdin: oStdin, oStdout: oStdout}, nil
-}
-
-func (p *listener) Dialer() jsonrpc2.Dialer {
-	if p.localDail {
-		return p
-	}
-	return nil
-}
-
-// -----------------------------------------------------------------------------
-
-// Dialer returns a jsonrpc2.Dialer based on stdin and stdout.
-func Dialer() jsonrpc2.Dialer {
-	return new(conn)
-}
-
-// Dial makes a new connection based on stdin and stdout, wraps the returned
-// reader and writer using the framer to make a stream, and then builds a
-// connection on top of that stream using the binder.
-//
-// The returned Connection will operate independently using the Preempter and/or
-// Handler provided by the Binder, and will release its own resources when the
-// connection is broken, but the caller may Close it earlier to stop accepting
-// (or sending) new requests.
-func Dial(binder jsonrpc2.Binder) (*jsonrpc2.Connection, error) {
-	return jsonrpc2.Dial(context.Background(), Dialer(), binder)
-}
-
-// -----------------------------------------------------------------------------
-
-// Listener returns a jsonrpc2.Listener based on stdin and stdout.
-func Listener(allowLocalDail bool) jsonrpc2.Listener {
-	l := &listener{localDail: allowLocalDail}
-	return l
-}
-
-// -----------------------------------------------------------------------------
diff --git a/x/jsonrpc2/wire.go b/x/jsonrpc2/wire.go
deleted file mode 100644
index 317b6598..00000000
--- a/x/jsonrpc2/wire.go
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (c) 2023 The GoPlus Authors (goplus.org). All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// 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.
-
-package jsonrpc2
-
-import (
-	"encoding/json"
-)
-
-// This file contains the go forms of the wire specification.
-// see http://www.jsonrpc.org/specification for details
-
-var (
-	// ErrParse is used when invalid JSON was received by the server.
-	ErrParse = NewError(-32700, "JSON RPC parse error")
-	// ErrInvalidRequest is used when the JSON sent is not a valid Request object.
-	ErrInvalidRequest = NewError(-32600, "JSON RPC invalid request")
-	// ErrMethodNotFound should be returned by the handler when the method does
-	// not exist / is not available.
-	ErrMethodNotFound = NewError(-32601, "JSON RPC method not found")
-	// ErrInvalidParams should be returned by the handler when method
-	// parameter(s) were invalid.
-	ErrInvalidParams = NewError(-32602, "JSON RPC invalid params")
-	// ErrInternal indicates a failure to process a call correctly
-	ErrInternal = NewError(-32603, "JSON RPC internal error")
-
-	// The following errors are not part of the json specification, but
-	// compliant extensions specific to this implementation.
-
-	// ErrServerOverloaded is returned when a message was refused due to a
-	// server being temporarily unable to accept any new messages.
-	ErrServerOverloaded = NewError(-32000, "JSON RPC overloaded")
-	// ErrUnknown should be used for all non coded errors.
-	ErrUnknown = NewError(-32001, "JSON RPC unknown error")
-	// ErrServerClosing is returned for calls that arrive while the server is closing.
-	ErrServerClosing = NewError(-32002, "JSON RPC server is closing")
-	// ErrClientClosing is a dummy error returned for calls initiated while the client is closing.
-	ErrClientClosing = NewError(-32003, "JSON RPC client is closing")
-)
-
-const wireVersion = "2.0"
-
-// wireCombined has all the fields of both Request and Response.
-// We can decode this and then work out which it is.
-type wireCombined struct {
-	VersionTag string          `json:"jsonrpc"`
-	ID         interface{}     `json:"id,omitempty"`
-	Method     string          `json:"method,omitempty"`
-	Params     json.RawMessage `json:"params,omitempty"`
-	Result     json.RawMessage `json:"result,omitempty"`
-	Error      *wireError      `json:"error,omitempty"`
-}
-
-// wireError represents a structured error in a Response.
-type wireError struct {
-	// Code is an error code indicating the type of failure.
-	Code int64 `json:"code"`
-	// Message is a short description of the error.
-	Message string `json:"message"`
-	// Data is optional structured data containing additional information about the error.
-	Data json.RawMessage `json:"data,omitempty"`
-}
-
-// NewError returns an error that will encode on the wire correctly.
-// The standard codes are made available from this package, this function should
-// only be used to build errors for application specific codes as allowed by the
-// specification.
-func NewError(code int64, message string) error {
-	return &wireError{
-		Code:    code,
-		Message: message,
-	}
-}
-
-func (err *wireError) Error() string {
-	return err.Message
-}
-
-func (err *wireError) Is(other error) bool {
-	w, ok := other.(*wireError)
-	if !ok {
-		return false
-	}
-	return err.Code == w.Code
-}


Test patch:
diff --git a/cl/compile_spx_test.go b/cl/compile_spx_test.go
index 28e0fd71..9d387a78 100644
--- a/cl/compile_spx_test.go
+++ b/cl/compile_spx_test.go
@@ -303,15 +303,15 @@ func onCloned() {
 
 import "github.com/goplus/gop/cl/internal/spx"
 
-type Game struct {
-	*spx.MyGame
-	Kai Kai
-}
 type Kai struct {
 	spx.Sprite
 	*Game
 	a int
 }
+type Game struct {
+	*spx.MyGame
+	Kai Kai
+}
 
 func (this *Game) onInit() {
 	spx.Gopt_Sprite_Clone__0(this.Kai)
@@ -345,6 +345,11 @@ import (
 	"github.com/goplus/gop/cl/internal/spx"
 )
 
+type Kai struct {
+	spx.Sprite
+	*index
+}
+
 var x float64 = spx.Rand__1(1.2)
 
 type index struct {
@@ -352,10 +357,6 @@ type index struct {
 	Kai Kai
 	t   spx.Sound
 }
-type Kai struct {
-	spx.Sprite
-	*index
-}
 
 func (this *index) MainEntry() {
 	spx.Gopt_MyGame_Run(this, "hzip://open.qiniu.us/weather/res.zip")
@@ -493,14 +494,14 @@ var (
 
 import "github.com/goplus/gop/cl/internal/spx2"
 
-type Game struct {
-	spx2.Game
-	Kai Kai
-}
 type Kai struct {
 	spx2.Sprite
 	*Game
 }
+type Game struct {
+	spx2.Game
+	Kai Kai
+}
 
 func (this *Game) MainEntry() {
 }
@@ -529,14 +530,14 @@ import (
 	"github.com/goplus/gop/cl/internal/spx2"
 )
 
-type Game struct {
-	spx2.Game
-	Kai Kai
-}
 type Kai struct {
 	spx2.Sprite
 	*Game
 }
+type Game struct {
+	spx2.Game
+	Kai Kai
+}
 
 func (this *Game) MainEntry() {
 	fmt.Println("Hi")
@@ -630,15 +631,15 @@ type info struct {
 	x int
 	y int
 }
-type Game struct {
-	*spx.MyGame
-	Kai Kai
-}
 type Kai struct {
 	spx.Sprite
 	*Game
 	a int
 }
+type Game struct {
+	*spx.MyGame
+	Kai Kai
+}
 
 func (this *Game) onInit() {
 	spx.Gopt_Sprite_Clone__0(this.Kai)
diff --git a/x/jsonrpc2/internal/stack/stacktest/stacktest.go b/x/jsonrpc2/internal/stack/stacktest/stacktest.go
deleted file mode 100644
index a5c58c46..00000000
--- a/x/jsonrpc2/internal/stack/stacktest/stacktest.go
+++ /dev/null
@@ -1,50 +0,0 @@
-// 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.
-
-package stacktest
-
-import (
-	"testing"
-	"time"
-
-	"github.com/goplus/gop/x/jsonrpc2/internal/stack"
-)
-
-// this is only needed to support pre 1.14 when testing.TB did not have Cleanup
-type withCleanup interface {
-	Cleanup(func())
-}
-
-// the maximum amount of time to wait for goroutines to clean themselves up.
-const maxWait = time.Second
-
-// NoLeak checks that a test (or benchmark) does not leak any goroutines.
-func NoLeak(t testing.TB) {
-	c, ok := t.(withCleanup)
-	if !ok {
-		return
-	}
-	before := stack.Capture()
-	c.Cleanup(func() {
-		var delta stack.Delta
-		start := time.Now()
-		delay := time.Millisecond
-		for {
-			after := stack.Capture()
-			delta = stack.Diff(before, after)
-			if len(delta.After) == 0 {
-				// no leaks
-				return
-			}
-			if time.Since(start) > maxWait {
-				break
-			}
-			time.Sleep(delay)
-			delay *= 2
-		}
-		// it's been long enough, and leaks are still present
-		summary := stack.Summarize(delta.After)
-		t.Errorf("goroutine leak detected:\n%+v", summary)
-	})
-}
diff --git a/x/jsonrpc2/jsonrpc2test/cases/testcase.go b/x/jsonrpc2/jsonrpc2test/cases/testcase.go
deleted file mode 100644
index 3a3bb375..00000000
--- a/x/jsonrpc2/jsonrpc2test/cases/testcase.go
+++ /dev/null
@@ -1,398 +0,0 @@
-// 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.
-
-package cases
-
-import (
-	"context"
-	"encoding/json"
-	"fmt"
-	"log"
-	"path"
-	"reflect"
-	"sync"
-	"testing"
-	"time"
-
-	"github.com/goplus/gop/x/jsonrpc2"
-	"github.com/goplus/gop/x/jsonrpc2/internal/stack/stacktest"
-)
-
-var callTests = []invoker{
-	call{"no_args", nil, true},
-	call{"one_string", "fish", "got:fish"},
-	call{"one_number", 10, "got:10"},
-	call{"join", []string{"a", "b", "c"}, "a/b/c"},
-	sequence{"notify", []invoker{
-		notify{"set", 3},
-		notify{"add", 5},
-		call{"get", nil, 8},
-	}},
-	sequence{"preempt", []invoker{
-		async{"a", "wait", "a"},
-		notify{"unblock", "a"},
-		collect{"a", true, false},
-	}},
-	sequence{"basic cancel", []invoker{
-		async{"b", "wait", "b"},
-		cancel{"b"},
-		collect{"b", nil, true},
-	}},
-	sequence{"queue", []invoker{
-		async{"a", "wait", "a"},
-		notify{"set", 1},
-		notify{"add", 2},
-		notify{"add", 3},
-		notify{"add", 4},
-		// call{"peek", nil, 0}, // accumulator will not have any adds yet
-		notify{"unblock", "a"},
-		collect{"a", true, false},
-		call{"get", nil, 10}, // accumulator now has all the adds
-	}},
-	sequence{"fork", []invoker{
-		async{"a", "fork", "a"},
-		notify{"set", 1},
-		notify{"add", 2},
-		notify{"add", 3},
-		notify{"add", 4},
-		call{"get", nil, 10}, // fork will not have blocked the adds
-		notify{"unblock", "a"},
-		collect{"a", true, false},
-	}},
-	sequence{"concurrent", []invoker{
-		async{"a", "fork", "a"},
-		notify{"unblock", "a"},
-		async{"b", "fork", "b"},
-		notify{"unblock", "b"},
-		collect{"a", true, false},
-		collect{"b", true, false},
-	}},
-}
-
-type binder struct {
-	framer  jsonrpc2.Framer
-	runTest func(*handler)
-}
-
-type handler struct {
-	conn        *jsonrpc2.Connection
-	accumulator int
-
-	mutex   sync.Mutex
-	waiters map[string]chan struct{}
-
-	calls map[string]*jsonrpc2.AsyncCall
-}
-
-type invoker interface {
-	Name() string
-	Invoke(t *testing.T, ctx context.Context, h *handler)
-}
-
-type notify struct {
-	method string
-	params interface{}
-}
-
-type call struct {
-	method string
-	params interface{}
-	expect interface{}
-}
-
-type async struct {
-	name   string
-	method string
-	params interface{}
-}
-
-type collect struct {
-	name   string
-	expect interface{}
-	fails  bool
-}
-
-type cancel struct {
-	name string
-}
-
-type sequence struct {
-	name  string
-	tests []invoker
-}
-
-type echo call
-
-type cancelParams struct{ ID int64 }
-
-func Test(t *testing.T, ctx context.Context, listener jsonrpc2.Listener, framer jsonrpc2.Framer, noLeak bool) {
-	if noLeak {
-		stacktest.NoLeak(t)
-	}
-	server := jsonrpc2.NewServer(ctx, listener, binder{framer, nil})
-	defer func() {
-		listener.Close()
-		if noLeak {
-			server.Wait()
-		}
-	}()
-	for _, test := range callTests {
-		t.Run(test.Name(), func(t *testing.T) {
-			client, err := jsonrpc2.Dial(ctx,
-				listener.Dialer(), binder{framer, func(h *handler) {
-					defer h.conn.Close()
-					ctx := context.Background()
-					test.Invoke(t, ctx, h)
-					if call, ok := test.(*call); ok {
-						// also run all simple call tests in echo mode
-						(*echo)(call).Invoke(t, ctx, h)
-					}
-				}})
-			if err != nil {
-				t.Fatal(err)
-			}
-			client.Wait()
-		})
-	}
-}
-
-func (test notify) Name() string { return test.method }
-func (test notify) Invoke(t *testing.T, ctx context.Context, h *handler) {
-	if err := h.conn.Notify(ctx, test.method, test.params); err != nil {
-		t.Fatalf("%v:Notify failed: %v", test.method, err)
-	}
-}
-
-func (test call) Name() string { return test.method }
-func (test call) Invoke(t *testing.T, ctx context.Context, h *handler) {
-	results := newResults(test.expect)
-	if err := h.conn.Call(ctx, test.method, test.params).Await(ctx, results); err != nil {
-		t.Fatalf("%v:Call failed: %v", test.method, err)
-	}
-	verifyResults(t, test.method, results, test.expect)
-}
-
-func (test echo) Invoke(t *testing.T, ctx context.Context, h *handler) {
-	results := newResults(test.expect)
-	if err := h.conn.Call(ctx, "echo", []interface{}{test.method, test.params}).Await(ctx, results); err != nil {
-		t.Fatalf("%v:Echo failed: %v", test.method, err)
-	}
-	verifyResults(t, test.method, results, test.expect)
-}
-
-func (test async) Name() string { return test.name }
-func (test async) Invoke(t *testing.T, ctx context.Context, h *handler) {
-	h.calls[test.name] = h.conn.Call(ctx, test.method, test.params)
-}
-
-func (test collect) Name() string { return test.name }
-func (test collect) Invoke(t *testing.T, ctx context.Context, h *handler) {
-	o := h.calls[test.name]
-	results := newResults(test.expect)
-	err := o.Await(ctx, results)
-	switch {
-	case test.fails && err == nil:
-		t.Fatalf("%v:Collect was supposed to fail", test.name)
-	case !test.fails && err != nil:
-		t.Fatalf("%v:Collect failed: %v", test.name, err)
-	}
-	verifyResults(t, test.name, results, test.expect)
-}
-
-func (test cancel) Name() string { return test.name }
-func (test cancel) Invoke(t *testing.T, ctx context.Context, h *handler) {
-	o := h.calls[test.name]
-	if err := h.conn.Notify(ctx, "cancel", &cancelParams{o.ID().Raw().(int64)}); err != nil {
-		t.Fatalf("%v:Collect failed: %v", test.name, err)
-	}
-}
-
-func (test sequence) Name() string { return test.name }
-func (test sequence) Invoke(t *testing.T, ctx context.Context, h *handler) {
-	for _, child := range test.tests {
-		child.Invoke(t, ctx, h)
-	}
-}
-
-// newResults makes a new empty copy of the expected type to put the results into
-func newResults(expect interface{}) interface{} {
-	switch e := expect.(type) {
-	case []interface{}:
-		var r []interface{}
-		for _, v := range e {
-			r = append(r, reflect.New(reflect.TypeOf(v)).Interface())
-		}
-		return r
-	case nil:
-		return nil
-	default:
-		return reflect.New(reflect.TypeOf(expect)).Interface()
-	}
-}
-
-// verifyResults compares the results to the expected values
-func verifyResults(t *testing.T, method string, results interface{}, expect interface{}) {
-	if expect == nil {
-		if results != nil {
-			t.Errorf("%v:Got results %+v where none expeted", method, expect)
-		}
-		return
-	}
-	val := reflect.Indirect(reflect.ValueOf(results)).Interface()
-	if !reflect.DeepEqual(val, expect) {
-		t.Errorf("%v:Results are incorrect, got %+v expect %+v", method, val, expect)
-	}
-}
-
-func (b binder) Bind(ctx context.Context, conn *jsonrpc2.Connection) jsonrpc2.ConnectionOptions {
-	h := &handler{
-		conn:    conn,
-		waiters: make(map[string]chan struct{}),
-		calls:   make(map[string]*jsonrpc2.AsyncCall),
-	}
-	if b.runTest != nil {
-		go b.runTest(h)
-	}
-	return jsonrpc2.ConnectionOptions{
-		Framer:    b.framer,
-		Preempter: h,
-		Handler:   h,
-	}
-}
-
-func (h *handler) waiter(name string) chan struct{} {
-	log.Println("waiter:", name)
-	h.mutex.Lock()
-	defer h.mutex.Unlock()
-	waiter := make(chan struct{})
-	h.waiters[name] = waiter
-	return waiter
-}
-
-func (h *handler) closeWaiter(name string) {
-	log.Println("closeWaiter:", name)
-	for !h.tryCloseWaiter(name) {
-		time.Sleep(time.Millisecond)
-	}
-}
-
-func (h *handler) tryCloseWaiter(name string) (ok bool) {
-	h.mutex.Lock()
-	defer h.mutex.Unlock()
-	waiter, ok := h.waiters[name]
-	if ok {
-		delete(h.waiters, name)
-		close(waiter)
-	}
-	return
-}
-
-func (h *handler) Preempt(ctx context.Context, req *jsonrpc2.Request) (interface{}, error) {
-	switch req.Method {
-	case "unblock":
-		var name string
-		if err := json.Unmarshal(req.Params, &name); err != nil {
-			return nil, fmt.Errorf("%w: %s", jsonrpc2.ErrParse, err)
-		}
-		h.closeWaiter(name)
-		return nil, nil
-	case "peek":
-		if len(req.Params) > 0 {
-			return nil, fmt.Errorf("%w: expected no params", jsonrpc2.ErrInvalidParams)
-		}
-		return h.accumulator, nil
-	case "cancel":
-		var params cancelParams
-		if err := json.Unmarshal(req.Params, &params); err != nil {
-			return nil, fmt.Errorf("%w: %s", jsonrpc2.ErrParse, err)
-		}
-		h.conn.Cancel(jsonrpc2.Int64ID(params.ID))
-		return nil, nil
-	default:
-		return nil, jsonrpc2.ErrNotHandled
-	}
-}
-
-func (h *handler) Handle(ctx context.Context, req *jsonrpc2.Request) (interface{}, error) {
-	switch req.Method {
-	case "no_args":
-		if len(req.Params) > 0 {
-			return nil, fmt.Errorf("%w: expected no params", jsonrpc2.ErrInvalidParams)
-		}
-		return true, nil
-	case "one_string":
-		var v string
-		if err := json.Unmarshal(req.Params, &v); err != nil {
-			return nil, fmt.Errorf("%w: %s", jsonrpc2.ErrParse, err)
-		}
-		return "got:" + v, nil
-	case "one_number":
-		var v int
-		if err := json.Unmarshal(req.Params, &v); err != nil {
-			return nil, fmt.Errorf("%w: %s", jsonrpc2.ErrParse, err)
-		}
-		return fmt.Sprintf("got:%d", v), nil
-	case "set":
-		var v int
-		if err := json.Unmarshal(req.Params, &v); err != nil {
-			return nil, fmt.Errorf("%w: %s", jsonrpc2.ErrParse, err)
-		}
-		h.accumulator = v
-		return nil, nil
-	case "add":
-		var v int
-		if err := json.Unmarshal(req.Params, &v); err != nil {
-			return nil, fmt.Errorf("%w: %s", jsonrpc2.ErrParse, err)
-		}
-		h.accumulator += v
-		return nil, nil
-	case "get":
-		if len(req.Params) > 0 {
-			return nil, fmt.Errorf("%w: expected no params", jsonrpc2.ErrInvalidParams)
-		}
-		return h.accumulator, nil
-	case "join":
-		var v []string
-		if err := json.Unmarshal(req.Params, &v); err != nil {
-			return nil, fmt.Errorf("%w: %s", jsonrpc2.ErrParse, err)
-		}
-		return path.Join(v...), nil
-	case "echo":
-		var v []interface{}
-		if err := json.Unmarshal(req.Params, &v); err != nil {
-			return nil, fmt.Errorf("%w: %s", jsonrpc2.ErrParse, err)
-		}
-		var result interface{}
-		err := h.conn.Call(ctx, v[0].(string), v[1]).Await(ctx, &result)
-		return result, err
-	case "wait":
-		var name string
-		if err := json.Unmarshal(req.Params, &name); err != nil {
-			return nil, fmt.Errorf("%w: %s", jsonrpc2.ErrParse, err)
-		}
-		select {
-		case <-h.waiter(name):
-			return true, nil
-		case <-ctx.Done():
-			return nil, ctx.Err()
-		}
-	case "fork":
-		var name string
-		if err := json.Unmarshal(req.Params, &name); err != nil {
-			return nil, fmt.Errorf("%w: %s", jsonrpc2.ErrParse, err)
-		}
-		waitFor := h.waiter(name)
-		go func() {
-			select {
-			case <-waitFor:
-				h.conn.Respond(req.ID, true, nil)
-			case <-ctx.Done():
-				h.conn.Respond(req.ID, nil, ctx.Err())
-			}
-		}()
-		return nil, jsonrpc2.ErrAsyncResponse
-	default:
-		return nil, jsonrpc2.ErrNotHandled
-	}
-}
diff --git a/x/jsonrpc2/jsonrpc2test/jsonrpc2_test.go b/x/jsonrpc2/jsonrpc2test/jsonrpc2_test.go
deleted file mode 100644
index 5093c5ed..00000000
--- a/x/jsonrpc2/jsonrpc2test/jsonrpc2_test.go
+++ /dev/null
@@ -1,24 +0,0 @@
-// 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.
-
-package jsonrpc2test_test
-
-import (
-	"context"
-	"testing"
-
-	"github.com/goplus/gop/x/jsonrpc2"
-	"github.com/goplus/gop/x/jsonrpc2/jsonrpc2test"
-	"github.com/goplus/gop/x/jsonrpc2/jsonrpc2test/cases"
-)
-
-func TestNetPipe(t *testing.T) {
-	jsonrpc2.SetDebug(jsonrpc2.DbgFlagCall)
-	ctx := context.Background()
-	listener, err := jsonrpc2test.NetPipeListener(ctx)
-	if err != nil {
-		t.Fatal(err)
-	}
-	cases.Test(t, ctx, listener, jsonrpc2.HeaderFramer(), true)
-}
diff --git a/x/jsonrpc2/jsonrpc2test/pipe.go b/x/jsonrpc2/jsonrpc2test/pipe.go
deleted file mode 100644
index 269d208d..00000000
--- a/x/jsonrpc2/jsonrpc2test/pipe.go
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2023 The GoPlus Authors (goplus.org). All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// 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.
-
-package jsonrpc2test
-
-import (
-	"context"
-	"io"
-	"net"
-
-	"github.com/goplus/gop/x/jsonrpc2"
-)
-
-// NetPipeListener returns a new Listener that listens using net.Pipe.
-// It is only possibly to connect to it using the Dialer returned by the
-// Dialer method, each call to that method will generate a new pipe the other
-// side of which will be returned from the Accept call.
-func NetPipeListener(ctx context.Context) (jsonrpc2.Listener, error) {
-	return &netPiper{
-		done:   make(chan struct{}),
-		dialed: make(chan io.ReadWriteCloser),
-	}, nil
-}
-
-// netPiper is the implementation of Listener build on top of net.Pipes.
-type netPiper struct {
-	done   chan struct{}
-	dialed chan io.ReadWriteCloser
-}
-
-// Accept blocks waiting for an incoming connection to the listener.
-func (l *netPiper) Accept(context.Context) (io.ReadWriteCloser, error) {
-	// Block until the pipe is dialed or the listener is closed,
-	// preferring the latter if already closed at the start of Accept.
-	select {
-	case <-l.done:
-		return nil, net.ErrClosed
-	default:
-	}
-	select {
-	case rwc := <-l.dialed:
-		return rwc, nil
-	case <-l.done:
-		return nil, net.ErrClosed
-	}
-}
-
-// Close will cause the listener to stop listening. It will not close any connections that have
-// already been accepted.
-func (l *netPiper) Close() error {
-	// unblock any accept calls that are pending
-	close(l.done)
-	return nil
-}
-
-func (l *netPiper) Dialer() jsonrpc2.Dialer {
-	return l
-}
-
-func (l *netPiper) Dial(ctx context.Context) (io.ReadWriteCloser, error) {
-	client, server := net.Pipe()
-
-	select {
-	case l.dialed <- server:
-		return client, nil
-
-	case <-l.done:
-		client.Close()
-		server.Close()
-		return nil, net.ErrClosed
-	}
-}
diff --git a/x/jsonrpc2/jsonrpc2test/pipe_test.go b/x/jsonrpc2/jsonrpc2test/pipe_test.go
deleted file mode 100644
index 01757b38..00000000
--- a/x/jsonrpc2/jsonrpc2test/pipe_test.go
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2023 The GoPlus Authors (goplus.org). All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package jsonrpc2test
-
-import (
-	"context"
-	"io"
-	"net"
-	"testing"
-)
-
-func TestNetPipeDone(t *testing.T) {
-	np := &netPiper{
-		done:   make(chan struct{}, 1),
-		dialed: make(chan io.ReadWriteCloser),
-	}
-	np.done <- struct{}{}
-	if f, err := np.Accept(context.Background()); f != nil || err != net.ErrClosed {
-		t.Fatal("np.Accept:", f, err)
-	}
-	np.done <- struct{}{}
-	if f, err := np.Dial(context.Background()); f != nil || err != net.ErrClosed {
-		t.Fatal("np.Dial:", f, err)
-	}
-}
diff --git a/x/jsonrpc2/stdio/jsonrpc2_test.go b/x/jsonrpc2/stdio/jsonrpc2_test.go
deleted file mode 100644
index d3207ebc..00000000
--- a/x/jsonrpc2/stdio/jsonrpc2_test.go
+++ /dev/null
@@ -1,27 +0,0 @@
-// 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.
-
-package stdio_test
-
-import (
-	"context"
-	"testing"
-
-	"github.com/goplus/gop/x/jsonrpc2"
-	"github.com/goplus/gop/x/jsonrpc2/jsonrpc2test/cases"
-	"github.com/goplus/gop/x/jsonrpc2/stdio"
-)
-
-func TestStdio(t *testing.T) {
-	jsonrpc2.SetDebug(jsonrpc2.DbgFlagAll)
-	ctx := context.Background()
-	listener := stdio.Listener(true)
-	cases.Test(t, ctx, listener, nil, false)
-}
-
-func TestDial(t *testing.T) {
-	stdio.Dial(jsonrpc2.BinderFunc(func(ctx context.Context, c *jsonrpc2.Connection) jsonrpc2.ConnectionOptions {
-		return jsonrpc2.ConnectionOptions{}
-	}))
-}
diff --git a/x/jsonrpc2/stdio/stdio_test.go b/x/jsonrpc2/stdio/stdio_test.go
deleted file mode 100644
index d9f02927..00000000
--- a/x/jsonrpc2/stdio/stdio_test.go
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2023 The GoPlus Authors (goplus.org). All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package stdio
-
-import (
-	"context"
-	"net"
-	"testing"
-
-	"github.com/goplus/gop/x/jsonrpc2"
-)
-
-func TestConn(t *testing.T) {
-	jsonrpc2.SetDebug(jsonrpc2.DbgFlagAll)
-	c := new(conn)
-	c.Dial(context.Background())
-	if err := c.Close(); err != nil {
-		t.Fatal("Close failed:", err)
-	}
-	if err := c.Close(); err != net.ErrClosed {
-		t.Fatal("Close:", err)
-	}
-	if _, err := c.Read(nil); err != net.ErrClosed {
-		t.Fatal("Read:", err)
-	}
-	if _, err := c.Write(nil); err != net.ErrClosed {
-		t.Fatal("Write:", err)
-	}
-}
-
-func TestListener(t *testing.T) {
-	l := new(listener)
-	if l.Dialer() != nil {
-		t.Fatal("Dialer: not nil?")
-	}
-	c, err := l.Dial(context.Background())
-	if err != nil {
-		t.Fatal("Dial failed:", err)
-	}
-	if _, err := l.Dial(context.Background()); err != ErrTooManyConnections {
-		t.Fatal("Dial:", err)
-	}
-	if err := c.Close(); err != nil {
-		t.Fatal("Close failed:", err)
-	}
-	if err := c.Close(); err != net.ErrClosed {
-		t.Fatal("Close:", err)
-	}
-	if _, err := c.Read(nil); err != net.ErrClosed {
-		t.Fatal("Read:", err)
-	}
-	if _, err := c.Write(nil); err != net.ErrClosed {
-		t.Fatal("Write:", err)
-	}
-	l.Close()
-	if err := l.Close(); err != net.ErrClosed {
-		t.Fatal("l.Close:", err)
-	}
-}