Skip to main content

Function Interceptor

FunctionInterceptor<FuncType> is at the heart of hyperion-core and creates a high performance wrapper around a given function and provides following important functionality:

  • observers that can observe function arguments or function return value
  • mappers that allow callbacks to modify arguments of the function before it is called, or return value of the function after it is called.
  • mechanism to prevent execution of the function

The type argument of the FunctionInterceptor<FuncType> determines the signature of the function that is intercepted. The signature of callbacks for the following api is computed based on this given type argument and hence all api provide a fully typed experience.

The following are main API of this class:

argument observers and mappers

The onBeforeCallObserverAdd(callback) method allows installing argument observer. The callback will be called before the original function is called. This callback can observe the value of the arguments, but cannot change them. The signature of this callback will be exactly the same as the original function, but it can return a boolean value. If any such callback returns true, then the original function won't be called; which is useful to implement security features or provide alternative implementations for the function.

The onBeforeCallMapperAdd(callback) method allows installing an argument mapper. The callback will be called before the original function is called. This callback recieves an array (similar to JavaScript arguments object) and can modify and return a new argument array with new values of the arguments. This callback is more expensive than the observer variant and should be used with care.

If multiple mappers are installed, the output of each callback is passed to the next one as input.

See FunctionInterceptor.test.ts for example code.

return value observers and mappers

The onAfterCallObserverAdd(callback) method allows installing return value observer. The callback recieves a value of the type of the original function return value and return void. This function is called original function is called.

The onAfterCallMapperAdd(callback) also allows the callback to change the return value of the function to something of the same type.

If multiple mappers are installed, the output of each callback is passed to the next one as input.

See FunctionInterceptor.test.ts for example code.

argument + return value mapper

Sometimes we might need to know the input arguments to make a modification to the return value. Or we might need to create intermediary values based on input argument before the function call and then use that value after the function call to process the output. We might even simply want to run to pieces of related code before and after a function (e.g. start time and end time of a function to measure its latency)

To make such cases easier, the onBeforeAndAfterCallMapperAdd(callback) method allows a callback to receive arguments of the function in an array (which it can update) and return a function that will be used to observe or map the return value of the function.

Note that this function is the most expensive form of interception and should be used only when really necessary.

See FunctionInterceptor.test.ts for example code.

extra data on the interceptor object

The FunctionInterceptor class creates an interceptor object which can also carry extra data. the setData<T>(dataPropName: string, value: T): void and getData<T>(dataPropName: string): T | undefined methods allow named properties to be added to this object.

A very common usecase to track if certain type of callback is added to an interceptor. While one can implement such functionality using combination of getData and setData, the helper testAndSet(dataPropName: string): boolean method provide this functionality out of the box.

All of the above methods have a corresponding ...Remove counterpart that allow removing a callback at any time. This is particularly useful at runtime if an observer has found the situation it was looking for and can remove the callback to reduce the performace overhead it adds.

Builtin JS interceptors

The hyperion-core package already contains ready main interceptors for the following JS objects

  • IGlobalThis provides interceptors for global methods such as (setTimeout, setInterval)
  • IPromise provies interceptos for all Promise methods and constructors
  • IRequre provide interceptors for typical implementations of js require funcationality which can be used to investigate modules and bootstrap further interception of their output.