Ejemplo n.º 1
0
 Esm5Renderer.prototype.addDefinitions = function (output, compiledClass, definitions) {
     var classSymbol = this.host.getClassSymbol(compiledClass.declaration);
     if (!classSymbol) {
         throw new Error("Compiled class does not have a valid symbol: " + compiledClass.name + " in " + compiledClass.declaration.getSourceFile().fileName);
     }
     var parent = classSymbol.valueDeclaration && classSymbol.valueDeclaration.parent;
     if (!parent || !ts.isBlock(parent)) {
         throw new Error("Compiled class declaration is not inside an IIFE: " + compiledClass.name + " in " + compiledClass.declaration.getSourceFile().fileName);
     }
     var returnStatement = parent.statements.find(function (statement) { return ts.isReturnStatement(statement); });
     if (!returnStatement) {
         throw new Error("Compiled class wrapper IIFE does not have a return statement: " + compiledClass.name + " in " + compiledClass.declaration.getSourceFile().fileName);
     }
     var insertionPoint = returnStatement.getFullStart();
     output.appendLeft(insertionPoint, '\n' + definitions);
 };
Ejemplo n.º 2
0
 /**
  * Parse the statement to extract the ESM5 parameter initializer if there is one.
  * If one is found, add it to the appropriate parameter in the `parameters` collection.
  *
  * The form we are looking for is:
  *
  * ```
  * if (arg === void 0) { arg = initializer; }
  * ```
  *
  * @param statement a statement that may be initializing an optional parameter
  * @param parameters the collection of parameters that were found in the function definition
  * @returns true if the statement was a parameter initializer
  */
 function reflectParamInitializer(statement, parameters) {
     if (ts.isIfStatement(statement) && isUndefinedComparison(statement.expression) &&
         ts.isBlock(statement.thenStatement) && statement.thenStatement.statements.length === 1) {
         var ifStatementComparison = statement.expression; // (arg === void 0)
         var thenStatement = statement.thenStatement.statements[0]; // arg = initializer;
         if (esm2015_host_1.isAssignmentStatement(thenStatement)) {
             var comparisonName_1 = ifStatementComparison.left.text;
             var assignmentName = thenStatement.expression.left.text;
             if (comparisonName_1 === assignmentName) {
                 var parameter = parameters.find(function (p) { return p.name === comparisonName_1; });
                 if (parameter) {
                     parameter.initializer = thenStatement.expression.right;
                     return true;
                 }
             }
         }
     }
     return false;
 }
Ejemplo n.º 3
0
 Esm5ReflectionHost.prototype.getClassSymbol = function (node) {
     var symbol = _super.prototype.getClassSymbol.call(this, node);
     if (symbol)
         return symbol;
     if (ts.isVariableDeclaration(node)) {
         var iifeBody = getIifeBody(node);
         if (!iifeBody)
             return undefined;
         var innerClassIdentifier = getReturnIdentifier(iifeBody);
         if (!innerClassIdentifier)
             return undefined;
         return this.checker.getSymbolAtLocation(innerClassIdentifier);
     }
     else if (ts.isFunctionDeclaration(node)) {
         // It might be the function expression inside the IIFE. We need to go 5 levels up...
         // 1. IIFE body.
         var outerNode = node.parent;
         if (!outerNode || !ts.isBlock(outerNode))
             return undefined;
         // 2. IIFE function expression.
         outerNode = outerNode.parent;
         if (!outerNode || !ts.isFunctionExpression(outerNode))
             return undefined;
         // 3. IIFE call expression.
         outerNode = outerNode.parent;
         if (!outerNode || !ts.isCallExpression(outerNode))
             return undefined;
         // 4. Parenthesis around IIFE.
         outerNode = outerNode.parent;
         if (!outerNode || !ts.isParenthesizedExpression(outerNode))
             return undefined;
         // 5. Outer variable declaration.
         outerNode = outerNode.parent;
         if (!outerNode || !ts.isVariableDeclaration(outerNode))
             return undefined;
         return this.getClassSymbol(outerNode);
     }
     return undefined;
 };
Ejemplo n.º 4
0
 function expandForwardRef(arg) {
     arg = unwrapExpression(arg);
     if (!ts.isArrowFunction(arg) && !ts.isFunctionExpression(arg)) {
         return null;
     }
     var body = arg.body;
     // Either the body is a ts.Expression directly, or a block with a single return statement.
     if (ts.isBlock(body)) {
         // Block body - look for a single return statement.
         if (body.statements.length !== 1) {
             return null;
         }
         var stmt = body.statements[0];
         if (!ts.isReturnStatement(stmt) || stmt.expression === undefined) {
             return null;
         }
         return stmt.expression;
     }
     else {
         // Shorthand body - return as an expression.
         return body;
     }
 }
Ejemplo n.º 5
0
 Esm5ReflectionHost.prototype.getStatementsForClass = function (classSymbol) {
     var classDeclaration = classSymbol.valueDeclaration;
     return ts.isBlock(classDeclaration.parent) ? Array.from(classDeclaration.parent.statements) :
         [];
 };
Ejemplo n.º 6
0
// Determine if a node matched the structure of a downleveled TS class.
function isDownleveledClass(node) {
    if (!ts.isVariableStatement(node)) {
        return false;
    }
    if (node.declarationList.declarations.length !== 1) {
        return false;
    }
    const variableDeclaration = node.declarationList.declarations[0];
    if (!ts.isIdentifier(variableDeclaration.name)
        || !variableDeclaration.initializer) {
        return false;
    }
    let potentialClass = variableDeclaration.initializer;
    // TS 2.3 has an unwrapped class IIFE
    // TS 2.4 uses a function expression wrapper
    // TS 2.5 uses an arrow function wrapper
    if (ts.isParenthesizedExpression(potentialClass)) {
        potentialClass = potentialClass.expression;
    }
    if (!ts.isCallExpression(potentialClass) || potentialClass.arguments.length > 1) {
        return false;
    }
    let wrapperBody;
    if (ts.isFunctionExpression(potentialClass.expression)) {
        wrapperBody = potentialClass.expression.body;
    }
    else if (ts.isArrowFunction(potentialClass.expression)
        && ts.isBlock(potentialClass.expression.body)) {
        wrapperBody = potentialClass.expression.body;
    }
    else {
        return false;
    }
    if (wrapperBody.statements.length === 0) {
        return false;
    }
    const functionExpression = potentialClass.expression;
    const functionStatements = wrapperBody.statements;
    // need a minimum of two for a function declaration and return statement
    if (functionStatements.length < 2) {
        return false;
    }
    // The variable name should be the class name.
    const className = variableDeclaration.name.text;
    const firstStatement = functionStatements[0];
    // find return statement - may not be last statement
    let returnStatement;
    for (let i = functionStatements.length - 1; i > 0; i--) {
        if (ts.isReturnStatement(functionStatements[i])) {
            returnStatement = functionStatements[i];
            break;
        }
    }
    if (returnStatement == undefined
        || returnStatement.expression == undefined
        || !ts.isIdentifier(returnStatement.expression)) {
        return false;
    }
    if (functionExpression.parameters.length === 0) {
        // potential non-extended class or wrapped es2015 class
        return (ts.isFunctionDeclaration(firstStatement) || ts.isClassDeclaration(firstStatement))
            && firstStatement.name !== undefined
            && firstStatement.name.text === className
            && returnStatement.expression.text === firstStatement.name.text;
    }
    else if (functionExpression.parameters.length !== 1) {
        return false;
    }
    // Potential extended class
    const functionParameter = functionExpression.parameters[0];
    if (!ts.isIdentifier(functionParameter.name)
        || functionParameter.name.text !== superParameterName) {
        return false;
    }
    if (functionStatements.length < 3 || !ts.isExpressionStatement(firstStatement)) {
        return false;
    }
    if (!ts.isCallExpression(firstStatement.expression)) {
        return false;
    }
    const extendCallExpression = firstStatement.expression;
    let functionName;
    if (ts.isIdentifier(extendCallExpression.expression)) {
        functionName = extendCallExpression.expression.text;
    }
    else if (ts.isPropertyAccessExpression(extendCallExpression.expression)) {
        functionName = extendCallExpression.expression.name.text;
    }
    if (!functionName || !functionName.endsWith(extendsHelperName)) {
        return false;
    }
    if (extendCallExpression.arguments.length === 0) {
        return false;
    }
    const lastArgument = extendCallExpression.arguments[extendCallExpression.arguments.length - 1];
    if (!ts.isIdentifier(lastArgument) || lastArgument.text !== functionParameter.name.text) {
        return false;
    }
    const secondStatement = functionStatements[1];
    return ts.isFunctionDeclaration(secondStatement)
        && secondStatement.name !== undefined
        && className.endsWith(secondStatement.name.text)
        && returnStatement.expression.text === secondStatement.name.text;
}