wa-lang.org/wazero@v1.0.2/experimental/listener.go (about)

     1  package experimental
     2  
     3  import (
     4  	"context"
     5  
     6  	"wa-lang.org/wazero/api"
     7  )
     8  
     9  // FunctionListenerFactoryKey is a context.Context Value key. Its associated value should be a FunctionListenerFactory.
    10  //
    11  // See https://github.com/tetratelabs/wazero/issues/451
    12  type FunctionListenerFactoryKey struct{}
    13  
    14  // FunctionListenerFactory returns FunctionListeners to be notified when a
    15  // function is called.
    16  type FunctionListenerFactory interface {
    17  	// NewListener returns a FunctionListener for a defined function. If nil is
    18  	// returned, no listener will be notified.
    19  	NewListener(api.FunctionDefinition) FunctionListener
    20  }
    21  
    22  // FunctionListener can be registered for any function via
    23  // FunctionListenerFactory to be notified when the function is called.
    24  type FunctionListener interface {
    25  	// Before is invoked before a function is called. The returned context will
    26  	// be used as the context of this function call.
    27  	//
    28  	// # Params
    29  	//
    30  	//   - ctx: the context of the caller function which must be the same
    31  	//	   instance or parent of the result.
    32  	//   - def: the function definition.
    33  	//   - paramValues:  api.ValueType encoded parameters.
    34  	Before(ctx context.Context, def api.FunctionDefinition, paramValues []uint64) context.Context
    35  
    36  	// After is invoked after a function is called.
    37  	//
    38  	// # Params
    39  	//
    40  	//   - ctx: the context returned by Before.
    41  	//   - def: the function definition.
    42  	//   - err: nil if the function didn't err
    43  	//   - resultValues: api.ValueType encoded results.
    44  	After(ctx context.Context, def api.FunctionDefinition, err error, resultValues []uint64)
    45  }
    46  
    47  // TODO: We need to add tests to enginetest to ensure contexts nest. A good test can use a combination of call and call
    48  // indirect in terms of depth and breadth. The test could show a tree 3 calls deep where the there are a couple calls at
    49  // each depth under the root. The main thing this can help prevent is accidentally swapping the context internally.
    50  
    51  // TODO: Errors aren't handled, and the After hook should accept one along with the result values.
    52  
    53  // TODO: The context parameter of the After hook is not the same as the Before hook. This means interceptor patterns
    54  // are awkward. e.g. something like timing is difficult as it requires propagating a stack. Otherwise, nested calls will
    55  // overwrite each other's "since" time. Propagating a stack is further awkward as the After hook needs to know the
    56  // position to read from which might be subtle.