For example, I would like to be able to execute a(b)(c) where a, b, and c are proxy functions that I create.
So far I wrote the following piece of code:
function createProxy(funcName) {
const proxy = new Proxy(function () {}, {
apply(target, thisArg, args) {
result += `${funcName} `;
// Process and log each argument's name if it has a mapped proxy
args.forEach((arg) => {
if (proxiesMap.has(arg)) {
const argName = proxiesMap.get(arg);
result += `${argName} `;
}
});
// Return the proxy for chaining if no arguments, or pass through argument proxy if it exists
return args.length > 0 ? args[0] : proxy;
}
});
// Store the mapping from proxy to name
proxiesMap.set(proxy, funcName);
proxiedValues.add(funcName);
return proxy;
}
This is not really what I want, because if we have multiple statements that are executed on different lines, this will output:
a(b)(c);
d(e);
The above is outputting a b b c c d d e (due to appending the middle calls twice because on one hand they are function names on another hand they are arguments). The above should result in:
a b c
d e
I had another idea but it led to the same result:
function createProxy(param) {
let isFirstCall = true;
const proxy = function(...args) {
if (isFirstCall) {
result += `${param} `;
isFirstCall = false;
}
// Invoke any function arguments
args.forEach(arg => {
if (typeof arg === 'function') {
arg();
}
});
// Return the same function for chaining
return placeholder;
};
// Wrap with proxy
return new Proxy(placeholder, {
apply(target, thisArg, args) {
return target(...args);
}
});
}
The eventual execution of these proxies is demonstrated below:
// Get all parameter names
const paramNames = getParamNames(fn);
// Create proxies for all parameters
const args = paramNames.map(name => createProxy(name));
// Invoke the function with proxied arguments
fn(...args);
Below is a working snippet of the first code:
fn = (
(a, b, c, d) => { a(b)(c); b(c)(d); }
);
let result = "";
// Registry to keep track of proxies
const proxiedValues = new Set();
const proxiesMap = new WeakMap();
// Function to create a proxy for a given function name
function createProxy(funcName) {
const proxy = new Proxy(function () {}, {
apply(target, thisArg, args) {
result += `${funcName} `;
// Process and log each argument's name if it has a mapped proxy
args.forEach((arg) => {
if (proxiesMap.has(arg)) {
const argName = proxiesMap.get(arg);
result += `${argName} `;
}
});
// Return the proxy for chaining if no arguments, or pass through argument proxy if it exists
return args.length > 0 ? args[0] : proxy;
}
});
// Store the mapping from proxy to name
proxiesMap.set(proxy, funcName);
proxiedValues.add(funcName);
return proxy;
}
// Extract parameter names from the function
function getParamNames(func) {
const code = func.toString();
const result = code
.slice(code.indexOf('(') + 1, code.indexOf(')'))
.match(/([^\s,]+)/g);
return result === null ? [] : result;
}
// Get all parameter names
const paramNames = getParamNames(fn);
// Create proxies for all parameters
const args = paramNames.map(name => createProxy(name));
// Invoke the function with proxied arguments
fn(...args);
// Log the accumulated result
console.log(result.trim());
Where am I going wrong in function chaining proxieS?