Example #1
0
/**
 * Takes an object, and recursively converts it to a Babel AST literal node. This handles strings,
 * numbers, booleans, basic objects, and Arrays. This cannot handle circular references.
 * @param obj - The object to convert.
 * @returns A babel AST node.
 */
function objectToLiteral(obj: any): any {
  if (
    typeof obj === 'string' ||
    typeof obj === 'number' ||
    typeof obj === 'boolean' ||
    obj === null
  ) {
    // abc, 123, true, false, null
    return t.literal(obj);
  } else if (obj === undefined) {
    // undefined
    return t.identifier('undefined');
  } else if (Array.isArray(obj)) {
    // [...]
    return t.arrayExpression(obj.map(elem => objectToLiteral(elem)));
  } else if (obj instanceof Map) {
    return t.newExpression(
      t.identifier('Map'), obj.size
        // new Map([...])
        ? [objectToLiteral(Array.from(obj.entries()))]
        // new Map()
        : null
    );
  } else if (typeof obj === 'object') {
    // {a: 1, b: 2}
    return t.objectExpression(
      Object.keys(obj).map(key =>
        t.property('init', t.identifier(key), objectToLiteral(obj[key]))
      )
    );
  }

  throw new Error(`Cannot convert unknown type ${typeof obj} to literal.`);
}
Example #2
0
/**
 * Takes an object, and recursively converts it to a Babel AST literal node. This handles strings,
 * numbers, booleans, basic objects, and Arrays. This cannot handle circular references.
 * @param obj - The object to convert.
 * @returns A babel AST node.
 */
function objectToLiteral(obj: any): any {
  if (typeof obj === 'string' || typeof obj === 'number' || typeof obj === 'boolean') {
    return t.literal(obj);
  } else if (obj instanceof Array) {
    return t.arrayExpression(obj.map(elem => objectToLiteral(elem)));
  } else if (typeof obj === 'object') {
    return t.objectExpression(Object.keys(obj).map(key => {
      return t.Property('init', t.identifier(key), objectToLiteral(obj[key]));
    }));
  }

  throw new Error(`Cannot convert unkown type ${typeof obj} to literal.`);
}
Example #3
0
/**
 * Helper function that generates a remote constructor proxy.
 * @param className - The name of the interface.
 * @param constructorArgs - The types of the arguments to the constructor.
 * @returns A MethodDefinition node that can be added to a ClassBody.
 */
function generateRemoteConstructor(className: string, constructorArgs: Array<Parameter>) {

  // arg0, .... argN
  const args = constructorArgs.map((arg, i) => t.identifier(`arg${i}`));
  // [arg0, ... argN]
  const argsArray = t.arrayExpression(args);
  // [argType0, ... argTypeN]
  const argTypes = t.arrayExpression(constructorArgs.map(objectToLiteral));

  // client.createRemoteObject(className, this, [arg0, arg1, .... argN], [argType0 ... argTypeN])
  const rpcCallExpression = t.callExpression(
    createRemoteObjectExpression,
    [
      t.literal(className),
      t.thisExpression(),
      argsArray,
      argTypes,
    ]
  );

  // constructor(arg0, arg1, ..., argN) { ... }
  const constructor = t.FunctionExpression(null, args, t.blockStatement([rpcCallExpression]));
  return t.methodDefinition(t.identifier('constructor'), constructor, 'constructor', false, false);
}