atom-nuclide
Version:
A unified developer experience for web and mobile development, built as a suite of features on top of Atom to provide hackability and the support of an active community.
398 lines (336 loc) • 24.9 kB
JavaScript
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.generateProxy = generateProxy;
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
/*
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the LICENSE file in
* the root directory of this source tree.
*/
var _babelCoreLibTypes2;
function _babelCoreLibTypes() {
return _babelCoreLibTypes2 = _interopRequireWildcard(require('babel-core/lib/types'));
}
var _babelCoreLibGeneration2;
function _babelCoreLibGeneration() {
return _babelCoreLibGeneration2 = _interopRequireDefault(require('babel-core/lib/generation'));
}
var thenIdent = (_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('then');
var observableIdentifier = (_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('Observable');
var idIdentifier = (_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('id');
var moduleDotExportsExpression = (_babelCoreLibTypes2 || _babelCoreLibTypes()).memberExpression((_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('module'), (_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('exports'));
var clientIdentifier = (_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('_client');
// Functions that are implemented at the connection layer.
var callRemoteFunctionExpression = (_babelCoreLibTypes2 || _babelCoreLibTypes()).memberExpression(clientIdentifier, (_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('callRemoteFunction'));
var callRemoteMethodExpression = (_babelCoreLibTypes2 || _babelCoreLibTypes()).memberExpression(clientIdentifier, (_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('callRemoteMethod'));
var createRemoteObjectExpression = (_babelCoreLibTypes2 || _babelCoreLibTypes()).memberExpression(clientIdentifier, (_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('createRemoteObject'));
var disposeRemoteObjectExpression = (_babelCoreLibTypes2 || _babelCoreLibTypes()).memberExpression(clientIdentifier, (_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('disposeRemoteObject'));
var remoteModule = (_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('remoteModule');
var emptyObject = (_babelCoreLibTypes2 || _babelCoreLibTypes()).objectExpression([]);
var clientDotMarshalExpression = (_babelCoreLibTypes2 || _babelCoreLibTypes()).memberExpression(clientIdentifier, (_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('marshal'));
var clientDotUnmarshalExpression = (_babelCoreLibTypes2 || _babelCoreLibTypes()).memberExpression(clientIdentifier, (_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('unmarshal'));
var marshalCall = function marshalCall() {
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return (_babelCoreLibTypes2 || _babelCoreLibTypes()).callExpression(clientDotMarshalExpression, args);
};
var unmarshalCall = function unmarshalCall() {
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
}
return (_babelCoreLibTypes2 || _babelCoreLibTypes()).callExpression(clientDotUnmarshalExpression, args);
};
var clientDotMarshalArgsExpression = (_babelCoreLibTypes2 || _babelCoreLibTypes()).memberExpression(clientIdentifier, (_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('marshalArguments'));
// const clientDotUnmarshalArgsExpression
// = t.memberExpression(clientIdentifier, t.identifier('unmarshalArguments'));
/**
* Helper function that generates statments that can be used to marshal all of the
* arguments to a function.
* @param argumentTypes - An array of the types of the function's arguments.
* @returns An expression representing a promise that resolves to an array of the arguments.
*/
var marshalArgsCall = function marshalArgsCall(params) {
return (_babelCoreLibTypes2 || _babelCoreLibTypes()).callExpression(clientDotMarshalArgsExpression, [(_babelCoreLibTypes2 || _babelCoreLibTypes()).callExpression((_babelCoreLibTypes2 || _babelCoreLibTypes()).memberExpression((_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('Array'), (_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('from')), [(_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('arguments')]), objectToLiteral(params)]);
};
// const unmarshalArgsCall = params => t.callExpression(clientDotUnmarshalArgsExpression, [
// t.arguments,
// objectToLiteral(params),
// ]);
// Generates `trackOperationTiming(eventName, () => { return operation; })`
var trackOperationTimingCall = function trackOperationTimingCall(eventName, operation) {
return (_babelCoreLibTypes2 || _babelCoreLibTypes()).callExpression((_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('trackOperationTiming'), [(_babelCoreLibTypes2 || _babelCoreLibTypes()).literal(eventName), (_babelCoreLibTypes2 || _babelCoreLibTypes()).arrowFunctionExpression([], (_babelCoreLibTypes2 || _babelCoreLibTypes()).blockStatement([(_babelCoreLibTypes2 || _babelCoreLibTypes()).returnStatement(operation)]))]);
};
// Generates `Object.defineProperty(module.exports, name, {value: …})`
var objectDefinePropertyCall = function objectDefinePropertyCall(name, value) {
return (_babelCoreLibTypes2 || _babelCoreLibTypes()).callExpression((_babelCoreLibTypes2 || _babelCoreLibTypes()).memberExpression((_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('Object'), (_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('defineProperty')), [moduleDotExportsExpression, (_babelCoreLibTypes2 || _babelCoreLibTypes()).literal(name), (_babelCoreLibTypes2 || _babelCoreLibTypes()).objectExpression([(_babelCoreLibTypes2 || _babelCoreLibTypes()).property('init', (_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('value'), value)])]);
};
var dependenciesNodes = function dependenciesNodes(names) {
return {
// let name0, ... nameN;
declaration: (_babelCoreLibTypes2 || _babelCoreLibTypes()).variableDeclaration('let', names.map(function (name) {
return (_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier(name);
})),
// function() { name0 = arguments[0]; ... nameN = arguments[N]; }
injectionCall: (_babelCoreLibTypes2 || _babelCoreLibTypes()).functionExpression(null, [], (_babelCoreLibTypes2 || _babelCoreLibTypes()).blockStatement(names.map(function (name, i) {
return (_babelCoreLibTypes2 || _babelCoreLibTypes()).expressionStatement((_babelCoreLibTypes2 || _babelCoreLibTypes()).assignmentExpression('=', (_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier(name), (_babelCoreLibTypes2 || _babelCoreLibTypes()).memberExpression((_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('arguments'), (_babelCoreLibTypes2 || _babelCoreLibTypes()).literal(i))));
})))
};
};
/**
* Given the parsed result of a definition file, generate a remote proxy module
* that exports the definition's API, but internally calls RPC functions. The function
* does not return the proxy module directly, but rather returns a 'factory' method
* that should be called with a RpcConnection object. This factory method returns the
* remote module with the client object 'closed over,' and used to make the RPC calls.
* @param defs - The result of parsing the definition file.
* @returns The proxy factory method.
*/
function generateProxy(serviceName, preserveFunctionNames, defs) {
var statements = [];
// Declare remoteModule as empty object.
statements.push((_babelCoreLibTypes2 || _babelCoreLibTypes()).variableDeclaration('const', [(_babelCoreLibTypes2 || _babelCoreLibTypes()).variableDeclarator((_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('remoteModule'), emptyObject)]));
defs.forEach(function (definition) {
var name = definition.name;
switch (definition.kind) {
case 'function':
var functionName = preserveFunctionNames ? name : serviceName + '/' + name;
// Generate a remote proxy for each module-level function.
statements.push((_babelCoreLibTypes2 || _babelCoreLibTypes()).expressionStatement((_babelCoreLibTypes2 || _babelCoreLibTypes()).assignmentExpression('=', (_babelCoreLibTypes2 || _babelCoreLibTypes()).memberExpression(remoteModule, (_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier(name)), generateFunctionProxy(functionName, definition.type))));
break;
case 'interface':
// Generate a remote proxy for each remotable interface.
statements.push((_babelCoreLibTypes2 || _babelCoreLibTypes()).expressionStatement((_babelCoreLibTypes2 || _babelCoreLibTypes()).assignmentExpression('=', (_babelCoreLibTypes2 || _babelCoreLibTypes()).memberExpression(remoteModule, (_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier(name)), generateInterfaceProxy(definition))));
break;
case 'alias':
// nothing
break;
}
});
// Return the remote module.
statements.push((_babelCoreLibTypes2 || _babelCoreLibTypes()).returnStatement(remoteModule));
// Node module dependencies are added via the `inject` function, instead of
// requiring them. This eliminates having to worry about module resolution.
// In turn, that makes colocating the definition and the constructed proxy
// easier for internal and external services.
var deps = dependenciesNodes(['Observable', 'trackOperationTiming']);
// Wrap the remoteModule construction in a function that takes a RpcConnection
// object as an argument.
var func = (_babelCoreLibTypes2 || _babelCoreLibTypes()).arrowFunctionExpression([clientIdentifier], (_babelCoreLibTypes2 || _babelCoreLibTypes()).blockStatement(statements));
var assignment = (_babelCoreLibTypes2 || _babelCoreLibTypes()).assignmentExpression('=', moduleDotExportsExpression, func);
var program = (_babelCoreLibTypes2 || _babelCoreLibTypes()).program([
// !!!This module is not transpiled!!!
(_babelCoreLibTypes2 || _babelCoreLibTypes()).expressionStatement((_babelCoreLibTypes2 || _babelCoreLibTypes()).literal('use strict')), deps.declaration, (_babelCoreLibTypes2 || _babelCoreLibTypes()).expressionStatement(assignment), (_babelCoreLibTypes2 || _babelCoreLibTypes()).expressionStatement(objectDefinePropertyCall('inject', deps.injectionCall)), (_babelCoreLibTypes2 || _babelCoreLibTypes()).expressionStatement(objectDefinePropertyCall('defs', objectToLiteral(defs)))]);
// Use Babel to generate code from the AST.
return (0, (_babelCoreLibGeneration2 || _babelCoreLibGeneration()).default)(program).code;
}
/**
* Generate a remote proxy for a module-level function.
* @param func - The FunctionDefinition object that represents the functions API.
* @returns The proxy function (as an arrow function) that should be assigned to
* a property of the remote module.
*/
function generateFunctionProxy(name, funcType) {
// _client.callRemoteFunction(name, kind, args)
var callExpression = (_babelCoreLibTypes2 || _babelCoreLibTypes()).callExpression(callRemoteFunctionExpression, [(_babelCoreLibTypes2 || _babelCoreLibTypes()).literal(name), (_babelCoreLibTypes2 || _babelCoreLibTypes()).literal(funcType.returnType.kind), (_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('args')]);
// Promise.all(...).then(args => { return ...)
var argumentsPromise = marshalArgsCall(funcType.argumentTypes);
var marshalArgsAndCall = thenPromise(argumentsPromise, (_babelCoreLibTypes2 || _babelCoreLibTypes()).arrowFunctionExpression([(_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('args')], (_babelCoreLibTypes2 || _babelCoreLibTypes()).blockStatement([(_babelCoreLibTypes2 || _babelCoreLibTypes()).returnStatement(callExpression)])));
var result = generateUnmarshalResult(funcType.returnType, marshalArgsAndCall);
// function(arg0, ... argN) { return ... }
var args = funcType.argumentTypes.map(function (arg, i) {
return (_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('arg' + i);
});
return (_babelCoreLibTypes2 || _babelCoreLibTypes()).functionExpression(null, args, (_babelCoreLibTypes2 || _babelCoreLibTypes()).blockStatement([(_babelCoreLibTypes2 || _babelCoreLibTypes()).returnStatement(result)]));
}
/**
* Generate a remote proxy for an interface.
* @param def - The InterfaceDefinition object that encodes all if the interface's operations.
* @returns An anonymous ClassExpression node that can be assigned to a module property.
*/
function generateInterfaceProxy(def) {
var methodDefinitions = [];
// Generate proxies for static methods.
def.staticMethods.forEach(function (funcType, methodName) {
methodDefinitions.push((_babelCoreLibTypes2 || _babelCoreLibTypes()).methodDefinition((_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier(methodName), generateFunctionProxy(def.name + '/' + methodName, funcType), 'method', false, true));
});
// Generate constructor proxy.
if (def.constructorArgs != null) {
methodDefinitions.push(generateRemoteConstructor(def.name, def.constructorArgs));
}
// Generate proxies for instance methods.
var thisType = {
kind: 'named',
location: def.location,
name: def.name
};
def.instanceMethods.forEach(function (funcType, methodName) {
// dispose method is generated custom at the end
if (methodName === 'dispose') {
return;
}
var methodDefinition = generateRemoteDispatch(methodName, thisType, funcType);
methodDefinitions.push(methodDefinition);
});
// Generate the dispose method.
methodDefinitions.push(generateDisposeMethod());
return (_babelCoreLibTypes2 || _babelCoreLibTypes()).classExpression(null, (_babelCoreLibTypes2 || _babelCoreLibTypes()).classBody(methodDefinitions), null);
}
/**
* 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, constructorArgs) {
// arg0, .... argN
var args = constructorArgs.map(function (arg, i) {
return (_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('arg' + i);
});
// [arg0, ... argN]
var argsArray = (_babelCoreLibTypes2 || _babelCoreLibTypes()).arrayExpression(args);
// [argType0, ... argTypeN]
var argTypes = (_babelCoreLibTypes2 || _babelCoreLibTypes()).arrayExpression(constructorArgs.map(objectToLiteral));
// client.createRemoteObject(className, this, [arg0, arg1, .... argN], [argType0 ... argTypeN])
var rpcCallExpression = (_babelCoreLibTypes2 || _babelCoreLibTypes()).callExpression(createRemoteObjectExpression, [(_babelCoreLibTypes2 || _babelCoreLibTypes()).literal(className), (_babelCoreLibTypes2 || _babelCoreLibTypes()).thisExpression(), argsArray, argTypes]);
// constructor(arg0, arg1, ..., argN) { ... }
var constructor = (_babelCoreLibTypes2 || _babelCoreLibTypes()).FunctionExpression(null, args, (_babelCoreLibTypes2 || _babelCoreLibTypes()).blockStatement([rpcCallExpression]));
return (_babelCoreLibTypes2 || _babelCoreLibTypes()).methodDefinition((_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('constructor'), constructor, 'constructor', false, false);
}
/**
* Helper function that generates a proxy for an instance method of an interface.
* @param methodName - The name of the method.
* @param funcType - The type information for the function.
* @returns A MethodDefinition node that can be added to a ClassBody
*/
function generateRemoteDispatch(methodName, thisType, funcType) {
// _client.callRemoteMethod(this, methodName, returnType, args)
var remoteMethodCall = (_babelCoreLibTypes2 || _babelCoreLibTypes()).callExpression(callRemoteMethodExpression, [idIdentifier, (_babelCoreLibTypes2 || _babelCoreLibTypes()).literal(methodName), (_babelCoreLibTypes2 || _babelCoreLibTypes()).literal(funcType.returnType.kind), (_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('args')]);
// _client.marshal(this, thisType).then(id => { return ... })
var idThenCall = thenPromise(generateTransformStatement((_babelCoreLibTypes2 || _babelCoreLibTypes()).thisExpression(), thisType, true), (_babelCoreLibTypes2 || _babelCoreLibTypes()).arrowFunctionExpression([idIdentifier], (_babelCoreLibTypes2 || _babelCoreLibTypes()).blockStatement([(_babelCoreLibTypes2 || _babelCoreLibTypes()).returnStatement(remoteMethodCall)])));
// Promise.all(...).then(args => { return ... })
var argumentsPromise = marshalArgsCall(funcType.argumentTypes);
var marshallThenCall = thenPromise(argumentsPromise, (_babelCoreLibTypes2 || _babelCoreLibTypes()).arrowFunctionExpression([(_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('args')], (_babelCoreLibTypes2 || _babelCoreLibTypes()).blockStatement([(_babelCoreLibTypes2 || _babelCoreLibTypes()).returnStatement(idThenCall)])));
// methodName(arg0, ... argN) { return ... }
var funcTypeArgs = funcType.argumentTypes.map(function (arg, i) {
return (_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('arg' + i);
});
var result = generateUnmarshalResult(funcType.returnType, marshallThenCall);
var funcExpression = (_babelCoreLibTypes2 || _babelCoreLibTypes()).functionExpression(null, funcTypeArgs, (_babelCoreLibTypes2 || _babelCoreLibTypes()).blockStatement([
// Wrap in trackOperationTiming if result returns a promise.
(_babelCoreLibTypes2 || _babelCoreLibTypes()).returnStatement(funcType.returnType.kind === 'promise' ? trackOperationTimingCall(thisType.name + '.' + methodName, result) : result)]));
return (_babelCoreLibTypes2 || _babelCoreLibTypes()).methodDefinition((_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier(methodName), funcExpression, 'method', false, false);
}
function generateUnmarshalResult(returnType, rpcCallExpression) {
switch (returnType.kind) {
case 'void':
return rpcCallExpression;
case 'promise':
var promiseTransformer = generateValueTransformer(returnType.type);
return thenPromise(rpcCallExpression, promiseTransformer);
case 'observable':
// rpcCallExpression is a call which returns Promise<Observable<unmarshalled result>>
// Observable.fromPromise(rpcCallExpression)
var callObservable = (_babelCoreLibTypes2 || _babelCoreLibTypes()).callExpression((_babelCoreLibTypes2 || _babelCoreLibTypes()).memberExpression(observableIdentifier, (_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('fromPromise')), [rpcCallExpression]);
// ... .flatMap(id => id)
var unmarshalledValues = (_babelCoreLibTypes2 || _babelCoreLibTypes()).callExpression((_babelCoreLibTypes2 || _babelCoreLibTypes()).memberExpression(callObservable, (_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('concatMap')), [(_babelCoreLibTypes2 || _babelCoreLibTypes()).arrowFunctionExpression([idIdentifier], idIdentifier)]);
// Map the events through the appropriate marshaller. We use concatMap instead of
// flatMap to ensure that the order doesn't change, in case one event takes especially long
// to marshal.
//
// ... .concatMap(value => _client.unmarshal(value, returnType))
var observableTransformer = generateValueTransformer(returnType.type);
var unmarshalledObservable = (_babelCoreLibTypes2 || _babelCoreLibTypes()).callExpression((_babelCoreLibTypes2 || _babelCoreLibTypes()).memberExpression(unmarshalledValues, (_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('concatMap')), [observableTransformer]);
// And finally, convert to a ConnectableObservable with publish.
return (_babelCoreLibTypes2 || _babelCoreLibTypes()).callExpression((_babelCoreLibTypes2 || _babelCoreLibTypes()).memberExpression(unmarshalledObservable, (_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('publish')), []);
default:
throw new Error('Unkown return type ' + returnType.kind + '.');
}
}
// value => _client.unmarshal(value, type)
function generateValueTransformer(type) {
var value = (_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('value');
return (_babelCoreLibTypes2 || _babelCoreLibTypes()).arrowFunctionExpression([value], (_babelCoreLibTypes2 || _babelCoreLibTypes()).blockStatement([(_babelCoreLibTypes2 || _babelCoreLibTypes()).returnStatement(generateTransformStatement(value, type, false))]));
}
/**
* Helper method that generates the dispose method for a class. The dispose method
* calls `_client.disposeRemoteObject` with the object's id as a parameter.
* @returns A MethodDefinition node that can be attached to a class body.
*/
function generateDisposeMethod() {
// return _client.disposeRemoteObject(this);
var returnStatement = (_babelCoreLibTypes2 || _babelCoreLibTypes()).returnStatement((_babelCoreLibTypes2 || _babelCoreLibTypes()).callExpression(disposeRemoteObjectExpression, [(_babelCoreLibTypes2 || _babelCoreLibTypes()).thisExpression()]));
// dispose() { ... }
return (_babelCoreLibTypes2 || _babelCoreLibTypes()).methodDefinition((_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('dispose'), (_babelCoreLibTypes2 || _babelCoreLibTypes()).functionExpression(null, [], (_babelCoreLibTypes2 || _babelCoreLibTypes()).blockStatement([returnStatement])), 'method', false, false);
}
/**
* Helper function that generates a transformation statement for an object. This ammounts to
* a call either to _client.marshal or _client.unmarshal.
* @param id {Identifier} The identifier of the value to convert.
* @param type {Type} The type of the value to convert.
* @param marshal {boolean} - If true, then we are trying to marshal the value. If false, then
* we are trying to unmarshal.
*/
function generateTransformStatement(id, type, marshal) {
// The first argument is the value to be marshalled or unmarshalled.
// The second argument is the type object, which encodes all of the information required
// to marshal / unmarshal the value.
var convertArgs = [id, objectToLiteral(type)];
// If the type is parameterized, we send the parameters as an optional fourth argument.
if (type.param) {
convertArgs.push(objectToLiteral(type.param));
}
// Return the appropriate call.
return (marshal ? marshalCall : unmarshalCall).apply(this, convertArgs);
}
/**
* 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) {
if (typeof obj === 'string' || typeof obj === 'number' || typeof obj === 'boolean' || obj === null) {
// abc, 123, true, false, null
return (_babelCoreLibTypes2 || _babelCoreLibTypes()).literal(obj);
} else if (obj === undefined) {
// undefined
return (_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('undefined');
} else if (Array.isArray(obj)) {
// [...]
return (_babelCoreLibTypes2 || _babelCoreLibTypes()).arrayExpression(obj.map(function (elem) {
return objectToLiteral(elem);
}));
} else if (obj instanceof Map) {
return (_babelCoreLibTypes2 || _babelCoreLibTypes()).newExpression((_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier('Map'), obj.size
// new Map([...])
? [objectToLiteral(Array.from(obj.entries()))]
// new Map()
: null);
} else if (typeof obj === 'object') {
// {a: 1, b: 2}
return (_babelCoreLibTypes2 || _babelCoreLibTypes()).objectExpression(Object.keys(obj).map(function (key) {
return (_babelCoreLibTypes2 || _babelCoreLibTypes()).property('init', (_babelCoreLibTypes2 || _babelCoreLibTypes()).identifier(key), objectToLiteral(obj[key]));
}));
}
throw new Error('Cannot convert unknown type ' + typeof obj + ' to literal.');
}
/**
* Helper function that `.then`s on a promise.
* @param promiseExpression - An expression that will evaluate to a promise.
* @param functionExpression - A function to pass as an argument to `.then`
* @returns A CallExpression node that `.then`s on the provided promise.
*/
function thenPromise(promiseExpression, functionExpression) {
return (_babelCoreLibTypes2 || _babelCoreLibTypes()).callExpression((_babelCoreLibTypes2 || _babelCoreLibTypes()).memberExpression(promiseExpression, thenIdent), [functionExpression]);
}
/** Export private functions for unit-testing. */
var __test__ = {
generateTransformStatement: generateTransformStatement,
objectToLiteral: objectToLiteral
};
exports.__test__ = __test__;