Skip to content

Instantly share code, notes, and snippets.

@fabiospampinato
Created January 29, 2022 16:18
Show Gist options
  • Select an option

  • Save fabiospampinato/2b95da1bf59d6a25b79a4be35c7886a2 to your computer and use it in GitHub Desktop.

Select an option

Save fabiospampinato/2b95da1bf59d6a25b79a4be35c7886a2 to your computer and use it in GitHub Desktop.
proxy_traps_experiments.ts
/* IMPORT */
import {SYMBOL} from './constants';
import Observable from './observable';
import {ObservableCallable} from './types';
/* MAIN */
// The most optimized way to make an Observable class callable
// It has ~50% memory usage overhead over just creating the Observable class, which is the most memory efficient but classes are not callable
// It has ~50% startup time overhead over just creating the bound functions manually, which is the fastest for a low number of methods but always consumes a shitload of memory
// It has some runtime overhead since Proxy is used
const callable = (() => {
if ( false ) {
const proxy = (): void => {};
class ObservableTraps {
observable: Observable<unknown>;
constructor ( observable: Observable<unknown> ) {
this.observable = observable;
}
get ( target: unknown, property: number | string | symbol ) {
const observable = this.observable;
if ( property === SYMBOL ) return observable;
const value = observable[property];
const isFunction = ( typeof value === 'function' );
return isFunction ? value.bind ( observable ) : value;
}
set ( target: unknown, property: number | string | symbol, value: unknown ) {
this.observable[property] = value;
return true;
}
apply ( target: unknown, thisArg: unknown, args: unknown[] ) {
const observable = this.observable;
return observable.call.apply ( observable, args );
}
}
return ( observable: Observable<unknown> ): ObservableCallable<unknown> => {
const traps = new ObservableTraps ( observable );
return new Proxy ( proxy, traps );
};
} else {
const self = function () { return this };
const Traps = {
get ( target, property ) {
if ( property === SYMBOL ) return target ();
return target ()[property];
},
set ( target, property, value ) {
target ()[property] = value;
return true;
},
apply ( target, thisArg, args ) {
return target ().call ( ...args );
}
};
return observable => {
return new Proxy ( self.bind ( observable ), Traps );
};
}
})();
/* EXPORT */
export default callable;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment