Example #1
0
 [ t.thisExpression() ].concat(vars.map(function(v) {
   return t.conditionalExpression(
     t.binaryExpression('in', t.stringLiteral(v), t.logicalExpression('||', t.identifier(bag), t.objectExpression([]))),
     t.memberExpression(t.logicalExpression('||', t.identifier(bag), t.objectExpression([])), t.identifier(v)),
     t.conditionalExpression(
       t.binaryExpression('!==', t.unaryExpression('typeof', t.identifier(v)), t.stringLiteral('undefined')),
       t.identifier(v),
       t.identifier('undefined')
     )
   )
 }))
Example #2
0
 ast_buffer: function(ast) {
   return [t.expressionStatement(
           t.assignmentExpression('=',
             t.identifier('pug_html'),
             t.binaryExpression('+', t.identifier('pug_html'), ast)
           ))];
 },
Example #3
0
File: index.js Project: t-mart/gvd
function simplifyCharCodeAt(path) {
  var node = path.node;
  var charCodeCallExprNode = (t.isCallExpression(node.left)
  && t.isMemberExpression(node.left.callee)
  && t.isIdentifier(node.left.callee.property)
  && node.left.callee.property.name === 'charCodeAt') ?
    node.left :
    (t.isCallExpression(node.right)
    && t.isMemberExpression(node.right.callee)
    && t.isIdentifier(node.right.callee.property)
    && node.right.callee.property.name === 'charCodeAt') ?
      node.right :
      false;
  if (charCodeCallExprNode === false) return node;
  var indexLiteralNode = charCodeCallExprNode.arguments[0];
  if (!indexLiteralNode) return node;
  if (node.operator !== '===') return node;
  var asciiNode = t.valueToNode(String.fromCharCode(
    (charCodeCallExprNode === node.left ?
      node.right :
      node.left).value));
  var identifierIndexMemberNode = t.memberExpression(
    charCodeCallExprNode.callee.object,
    indexLiteralNode,
    true
  );
  return t.binaryExpression('===', identifierIndexMemberNode, asciiNode);
}
	beforeEach(function () {
		program = new Program();
		context = new HindleyMilnerContext(null, new TypeInferenceContext(program));
		rule = new ForStatementRefinementRule();
		init = t.assignmentExpression("=", t.identifier("x"), t.numericLiteral(10));
		test = t.binaryExpression("<", t.identifier("x"), t.numericLiteral(100));
		update = t.updateExpression("++", t.identifier("x"));
	});
					typeInferenceAnalysis.analyse = (node, typeEnvironment) => {
						++analyseCount;
						const recursiveCall = t.callExpression(t.identifier("successor"), [t.binaryExpression("-", t.identifier("x"), t.numericLiteral(-1))]);
						typeInferenceAnalysis.infer.withArgs(recursiveCall.callee).returns(funcT);
						program.symbolTable.setSymbol(recursiveCall.arguments[0].left, x);
						rule.refine(recursiveCall, context);

						return new Map([[null, typeEnvironment.setType(Symbol.RETURN, NumberType.create())]]);
					};
Example #6
0
 const ifStatement = cases.map((Case, index) => {
     const [consequent] = Case.consequent;
     if (!t.isBlockStatement(consequent)) {
         throw utils_1.codeFrameError(switchStatement.node, '含有 JSX 的 switch case 语句必须每种情况都用花括号 `{}` 包裹结果');
     }
     const block = t.blockStatement(consequent.body.filter(b => !t.isBreakStatement(b)));
     if (index !== cases.length - 1 && t.isNullLiteral(Case.test)) {
         throw utils_1.codeFrameError(Case, '含有 JSX 的 switch case 语句只有最后一个 case 才能是 default');
     }
     const test = Case.test === null ? t.nullLiteral() : t.binaryExpression('===', discriminant, Case.test);
     return { block, test };
 }).reduceRight((ifStatement, item) => {
Example #7
0
File: index.js Project: lxe/babel
  buildHas(ret: { type: "Identifier" }, call: { type: "CallExpression" }) {
    let body = this.body;

    body.push(t.variableDeclaration("var", [
      t.variableDeclarator(ret, call)
    ]));

    let retCheck;
    let has = this.has;
    let cases = [];

    if (has.hasReturn) {
      // typeof ret === "object"
      retCheck = buildRetCheck({
        RETURN: ret
      });
    }

    if (has.hasBreakContinue) {
      for (let key in has.map) {
        cases.push(t.switchCase(t.stringLiteral(key), [has.map[key]]));
      }

      if (has.hasReturn) {
        cases.push(t.switchCase(null, [retCheck]));
      }

      if (cases.length === 1) {
        let single = cases[0];
        body.push(t.ifStatement(
          t.binaryExpression("===", ret, single.test),
          single.consequent[0]
        ));
      } else {
        if (this.loop) {
          // https://github.com/babel/babel/issues/998
          for (let i = 0; i < cases.length; i++) {
            let caseConsequent = cases[i].consequent[0];
            if (t.isBreakStatement(caseConsequent) && !caseConsequent.label) {
              caseConsequent.label = this.loopLabel = this.loopLabel || this.scope.generateUidIdentifier("loop");
            }
          }
        }

        body.push(t.switchStatement(ret, cases));
      }
    } else {
      if (has.hasReturn) {
        body.push(retCheck);
      }
    }
  }
Example #8
0
File: rest.js Project: ANWSY/babel
function optimiseLengthGetter(path, argsLengthExpression, argsId, offset) {
  if (offset) {
    path.parentPath.replaceWith(
      t.binaryExpression(
        "-",
        argsLengthExpression,
        t.numericLiteral(offset),
      )
    );
  } else {
    path.replaceWith(argsId);
  }
}
Example #9
0
File: index.js Project: ANWSY/babel
  specHandle(path: NodePath) {
    let property;
    let computed;
    let args;
    let thisReference;

    let parent = path.parent;
    let node = path.node;

    if (isIllegalBareSuper(node, parent)) {
      throw path.buildCodeFrameError(messages.get("classesIllegalBareSuper"));
    }

    if (t.isCallExpression(node)) {
      let callee = node.callee;
      if (t.isSuper(callee)) {
        return;
      } else if (isMemberExpressionSuper(callee)) {
        // super.test(); -> _get(Object.getPrototypeOf(objectRef.prototype), "test", this).call(this);
        property = callee.property;
        computed = callee.computed;
        args = node.arguments;
      }
    } else if (t.isMemberExpression(node) && t.isSuper(node.object)) {
      // super.name; -> _get(Object.getPrototypeOf(objectRef.prototype), "name", this);
      property = node.property;
      computed = node.computed;
    } else if (t.isUpdateExpression(node) && isMemberExpressionSuper(node.argument)) {
      let binary = t.binaryExpression(node.operator[0], node.argument, t.numericLiteral(1));
      if (node.prefix) {
        // ++super.foo; -> super.foo += 1;
        return this.specHandleAssignmentExpression(null, path, binary);
      } else {
        // super.foo++; -> let _ref = super.foo; super.foo = _ref + 1;
        let ref = path.scope.generateUidIdentifier("ref");
        return this.specHandleAssignmentExpression(ref, path, binary).concat(t.expressionStatement(ref));
      }
    } else if (t.isAssignmentExpression(node) && isMemberExpressionSuper(node.left)) {
      return this.specHandleAssignmentExpression(null, path, node);
    }

    if (!property) return;

    let superProperty = this.getSuperProperty(property, computed, thisReference);

    if (args) {
      return this.optimiseCall(superProperty, args);
    } else {
      return superProperty;
    }
  }
Example #10
0
File: rest.js Project: ANWSY/babel
function optimiseIndexGetter(path, argsId, offset) {
  let index;

  if (t.isNumericLiteral(path.parent.property)) {
    index = t.numericLiteral(path.parent.property.value + offset);
  } else {
    index = t.binaryExpression("+", path.parent.property, t.numericLiteral(offset));
  }

  path.parentPath.replaceWith(loadRest({
    ARGUMENTS: argsId,
    INDEX: index,
  }));
}
Example #11
0
 specHandleAssignmentExpression(ref, path, node) {
   if (node.operator === "=") {
     // super.name = "val"; -> _set(Object.getPrototypeOf(objectRef.prototype), "name", this);
     return this.setSuperProperty(node.left.property, node.right, node.left.computed);
   } else {
     // super.age += 2; -> let _ref = super.age; super.age = _ref + 2;
     ref = ref || path.scope.generateUidIdentifier("ref");
     return [
       t.variableDeclaration("var", [
         t.variableDeclarator(ref, node.left)
       ]),
       t.expressionStatement(
         t.assignmentExpression("=", node.left, t.binaryExpression(node.operator[0], ref, node.right))
       )
     ];
   }
 }
Example #12
0
function transform(options) {
    if (options.adapter) {
        adapter_1.setAdapter(options.adapter);
    }
    if (adapter_1.Adapter.type === "swan" /* swan */) {
        constant_1.setLoopOriginal('privateOriginal');
    }
    constant_1.THIRD_PARTY_COMPONENTS.clear();
    const code = options.isTyped
        ? ts.transpile(options.code, {
            jsx: ts.JsxEmit.Preserve,
            target: ts.ScriptTarget.ESNext,
            importHelpers: true,
            noEmitHelpers: true
        })
        : options.code;
    options.env = Object.assign({ 'process.env.TARO_ENV': options.adapter || 'weapp' }, options.env || {});
    options_1.setTransformOptions(options);
    utils_1.setting.sourceCode = code;
    // babel-traverse 无法生成 Hub
    // 导致 Path#getSource|buildCodeFrameError 都无法直接使用
    // 原因大概是 babylon.parse 没有生成 File 实例导致 scope 和 path 原型上都没有 `file`
    // 将来升级到 babel@7 可以直接用 parse 而不是 transform
    const ast = babel_core_1.transform(code, options_1.buildBabelTransformOptions()).ast;
    if (options.isNormal) {
        return { ast };
    }
    // transformFromAst(ast, code)
    let result;
    const componentSourceMap = new Map();
    const imageSource = new Set();
    const importSources = new Set();
    let componentProperies = [];
    let mainClass;
    let storeName;
    let renderMethod;
    let isImportTaro = false;
    babel_traverse_1.default(ast, {
        TemplateLiteral(path) {
            const nodes = [];
            const { quasis, expressions } = path.node;
            let index = 0;
            if (path.parentPath.isTaggedTemplateExpression()) {
                return;
            }
            for (const elem of quasis) {
                if (elem.value.cooked) {
                    nodes.push(t.stringLiteral(elem.value.cooked));
                }
                if (index < expressions.length) {
                    const expr = expressions[index++];
                    if (!t.isStringLiteral(expr, { value: '' })) {
                        nodes.push(expr);
                    }
                }
            }
            // + 号连接符必须保证第一和第二个 node 都是字符串
            if (!t.isStringLiteral(nodes[0]) && !t.isStringLiteral(nodes[1])) {
                nodes.unshift(t.stringLiteral(''));
            }
            let root = nodes[0];
            for (let i = 1; i < nodes.length; i++) {
                root = t.binaryExpression('+', root, nodes[i]);
            }
            path.replaceWith(root);
        },
        ClassDeclaration(path) {
            mainClass = path;
            const superClass = utils_1.getSuperClassCode(path);
            if (superClass) {
                try {
                    componentProperies = transform({
                        isRoot: false,
                        isApp: false,
                        code: superClass.code,
                        isTyped: true,
                        sourcePath: superClass.sourcePath,
                        outputPath: superClass.sourcePath
                    }).componentProperies;
                }
                catch (error) {
                    //
                }
            }
        },
        ClassExpression(path) {
            mainClass = path;
        },
        ClassMethod(path) {
            if (t.isIdentifier(path.node.key) && path.node.key.name === 'render') {
                renderMethod = path;
            }
        },
        IfStatement(path) {
            const consequent = path.get('consequent');
            if (!consequent.isBlockStatement()) {
                consequent.replaceWith(t.blockStatement([
                    consequent.node
                ]));
            }
        },
        CallExpression(path) {
            const callee = path.get('callee');
            if (utils_1.isContainJSXElement(path)) {
                return;
            }
            if (callee.isReferencedMemberExpression()) {
                const id = utils_1.findFirstIdentifierFromMemberExpression(callee.node);
                const property = callee.node.property;
                if (t.isIdentifier(property) && property.name.startsWith('on')) {
                    const funcExpr = path.findParent(p => p.isFunctionExpression());
                    if (funcExpr && funcExpr.isFunctionExpression()) {
                        const taroAPI = funcExpr.findParent(p => p.isCallExpression() && t.isMemberExpression(p.node.callee) && t.isIdentifier(p.node.callee.object, { name: 'Taro' }));
                        if (taroAPI && taroAPI.isCallExpression()) {
                            throw utils_1.codeFrameError(funcExpr.node, '在回调函数使用从 props 传递的函数时,请把回调函数改造为箭头函数并一直使用 `this` 取值');
                        }
                    }
                }
                const calleeIds = getIdsFromMemberProps(callee.node);
                if (t.isIdentifier(id) && id.name.startsWith('on') && "alipay" /* alipay */ !== adapter_1.Adapter.type) {
                    const fullPath = buildFullPathThisPropsRef(id, calleeIds, path);
                    if (fullPath) {
                        path.replaceWith(t.callExpression(fullPath, path.node.arguments));
                    }
                }
            }
            if (callee.isReferencedIdentifier()) {
                const id = callee.node;
                const ids = [id.name];
                if (t.isIdentifier(id) && id.name.startsWith('on')) {
                    const funcExpr = path.findParent(p => p.isFunctionExpression());
                    if (funcExpr && funcExpr.isFunctionExpression()) {
                        const taroAPI = funcExpr.findParent(p => p.isCallExpression() && t.isMemberExpression(p.node.callee) && t.isIdentifier(p.node.callee.object, { name: 'Taro' }));
                        if (taroAPI && taroAPI.isCallExpression()) {
                            throw utils_1.codeFrameError(funcExpr.node, '在回调函数使用从 props 传递的函数时,请把回调函数改造为箭头函数并一直使用 `this` 取值');
                        }
                    }
                    const fullPath = buildFullPathThisPropsRef(id, ids, path);
                    if (fullPath) {
                        path.replaceWith(t.callExpression(fullPath, path.node.arguments));
                    }
                }
            }
        },
        // JSXIdentifier (path) {
        //   const parentPath = path.parentPath
        //   if (!parentPath.isJSXAttribute()) {
        //     return
        //   }
        //   const element = parentPath.parentPath
        //   if (!element.isJSXOpeningElement()) {
        //     return
        //   }
        //   const elementName = element.get('name')
        //   if (!elementName.isJSXIdentifier()) {
        //     return
        //   }
        //   if (DEFAULT_Component_SET.has(elementName.node.name)) {
        //     return
        //   }
        //   const expr = parentPath.get('value.expression')
        // },
        JSXElement(path) {
            const assignment = path.findParent(p => p.isAssignmentExpression());
            if (assignment && assignment.isAssignmentExpression() && !options.isTyped) {
                const left = assignment.node.left;
                if (t.isIdentifier(left)) {
                    const binding = assignment.scope.getBinding(left.name);
                    if (binding && binding.scope === assignment.scope) {
                        if (binding.path.isVariableDeclarator()) {
                            binding.path.node.init = path.node;
                            assignment.remove();
                        }
                        else {
                            throw utils_1.codeFrameError(path.node, '同一个作用域的JSX 变量延时赋值没有意义。详见:https://github.com/NervJS/taro/issues/550');
                        }
                    }
                }
            }
            const switchStatement = path.findParent(p => p.isSwitchStatement());
            if (switchStatement && switchStatement.isSwitchStatement()) {
                const { discriminant, cases } = switchStatement.node;
                const ifStatement = cases.map((Case, index) => {
                    const [consequent] = Case.consequent;
                    if (!t.isBlockStatement(consequent)) {
                        throw utils_1.codeFrameError(switchStatement.node, '含有 JSX 的 switch case 语句必须每种情况都用花括号 `{}` 包裹结果');
                    }
                    const block = t.blockStatement(consequent.body.filter(b => !t.isBreakStatement(b)));
                    if (index !== cases.length - 1 && t.isNullLiteral(Case.test)) {
                        throw utils_1.codeFrameError(Case, '含有 JSX 的 switch case 语句只有最后一个 case 才能是 default');
                    }
                    const test = Case.test === null ? t.nullLiteral() : t.binaryExpression('===', discriminant, Case.test);
                    return { block, test };
                }).reduceRight((ifStatement, item) => {
                    if (t.isNullLiteral(item.test)) {
                        ifStatement.alternate = item.block;
                        return ifStatement;
                    }
                    const newStatement = t.ifStatement(item.test, item.block, t.isBooleanLiteral(ifStatement.test, { value: false })
                        ? ifStatement.alternate
                        : ifStatement);
                    return newStatement;
                }, t.ifStatement(t.booleanLiteral(false), t.blockStatement([])));
                switchStatement.insertAfter(ifStatement);
                switchStatement.remove();
            }
            const isForStatement = (p) => p && (p.isForStatement() || p.isForInStatement() || p.isForOfStatement());
            const forStatement = path.findParent(isForStatement);
            if (isForStatement(forStatement)) {
                throw utils_1.codeFrameError(forStatement.node, '不行使用 for 循环操作 JSX 元素,详情:https://github.com/NervJS/taro/blob/master/packages/eslint-plugin-taro/docs/manipulate-jsx-as-array.md');
            }
            const loopCallExpr = path.findParent(p => utils_1.isArrayMapCallExpression(p));
            if (loopCallExpr && loopCallExpr.isCallExpression()) {
                const [func] = loopCallExpr.node.arguments;
                if (t.isArrowFunctionExpression(func) && !t.isBlockStatement(func.body)) {
                    func.body = t.blockStatement([
                        t.returnStatement(func.body)
                    ]);
                }
            }
        },
        JSXOpeningElement(path) {
            const { name } = path.node.name;
            const binding = path.scope.getBinding(name);
            if (process.env.NODE_ENV !== 'test' && constant_1.DEFAULT_Component_SET.has(name) && binding && binding.kind === 'module') {
                const bindingPath = binding.path;
                if (bindingPath.parentPath.isImportDeclaration()) {
                    const source = bindingPath.parentPath.node.source;
                    if (source.value !== constant_1.COMPONENTS_PACKAGE_NAME) {
                        throw utils_1.codeFrameError(bindingPath.parentPath.node, `内置组件名: '${name}' 只能从 ${constant_1.COMPONENTS_PACKAGE_NAME} 引入。`);
                    }
                }
            }
            if (name === 'Provider') {
                const modules = path.scope.getAllBindings('module');
                const providerBinding = Object.values(modules).some((m) => m.identifier.name === 'Provider');
                if (providerBinding) {
                    path.node.name = t.jSXIdentifier('view');
                    const store = path.node.attributes.find(attr => attr.name.name === 'store');
                    if (store && t.isJSXExpressionContainer(store.value) && t.isIdentifier(store.value.expression)) {
                        storeName = store.value.expression.name;
                    }
                    path.node.attributes = [];
                }
            }
            if (constant_1.IMAGE_COMPONENTS.has(name)) {
                for (const attr of path.node.attributes) {
                    if (attr.name.name === 'src') {
                        if (t.isStringLiteral(attr.value)) {
                            imageSource.add(attr.value.value);
                        }
                        else if (t.isJSXExpressionContainer(attr.value)) {
                            if (t.isStringLiteral(attr.value.expression)) {
                                imageSource.add(attr.value.expression.value);
                            }
                        }
                    }
                }
            }
        },
        JSXAttribute(path) {
            const { name, value } = path.node;
            if (options.jsxAttributeNameReplace) {
                for (const r in options.jsxAttributeNameReplace) {
                    if (options.jsxAttributeNameReplace.hasOwnProperty(r)) {
                        const element = options.jsxAttributeNameReplace[r];
                        if (t.isJSXIdentifier(name, { name: r })) {
                            path.node.name = t.jSXIdentifier(element);
                        }
                    }
                }
            }
            if (!t.isJSXIdentifier(name) || value === null || t.isStringLiteral(value) || t.isJSXElement(value)) {
                return;
            }
            const expr = value.expression;
            const exprPath = path.get('value.expression');
            const classDecl = path.findParent(p => p.isClassDeclaration());
            const classDeclName = classDecl && classDecl.isClassDeclaration() && lodash_1.get(classDecl, 'node.id.name', '');
            let isConverted = false;
            if (classDeclName) {
                isConverted = classDeclName === '_C' || classDeclName.endsWith('Tmpl');
            }
            if (!t.isBinaryExpression(expr, { operator: '+' }) && !t.isLiteral(expr) && name.name === 'style' && !isConverted) {
                const jsxID = path.findParent(p => p.isJSXOpeningElement()).get('name');
                if (jsxID && jsxID.isJSXIdentifier() && constant_1.DEFAULT_Component_SET.has(jsxID.node.name)) {
                    exprPath.replaceWith(t.callExpression(t.identifier(constant_1.INTERNAL_INLINE_STYLE), [expr]));
                }
            }
            if (name.name.startsWith('on')) {
                if (exprPath.isReferencedIdentifier()) {
                    const ids = [expr.name];
                    const fullPath = buildFullPathThisPropsRef(expr, ids, path);
                    if (fullPath) {
                        exprPath.replaceWith(fullPath);
                    }
                }
                if (exprPath.isReferencedMemberExpression()) {
                    const id = utils_1.findFirstIdentifierFromMemberExpression(expr);
                    const ids = getIdsFromMemberProps(expr);
                    if (t.isIdentifier(id)) {
                        const fullPath = buildFullPathThisPropsRef(id, ids, path);
                        if (fullPath) {
                            exprPath.replaceWith(fullPath);
                        }
                    }
                }
                // @TODO: bind 的处理待定
            }
        },
        ImportDeclaration(path) {
            const source = path.node.source.value;
            if (importSources.has(source)) {
                throw utils_1.codeFrameError(path.node, '无法在同一文件重复 import 相同的包。');
            }
            else {
                importSources.add(source);
            }
            const names = [];
            if (source === constant_1.TARO_PACKAGE_NAME) {
                isImportTaro = true;
                path.node.specifiers.push(t.importSpecifier(t.identifier(constant_1.INTERNAL_SAFE_GET), t.identifier(constant_1.INTERNAL_SAFE_GET)), t.importSpecifier(t.identifier(constant_1.INTERNAL_GET_ORIGNAL), t.identifier(constant_1.INTERNAL_GET_ORIGNAL)), t.importSpecifier(t.identifier(constant_1.INTERNAL_INLINE_STYLE), t.identifier(constant_1.INTERNAL_INLINE_STYLE)), t.importSpecifier(t.identifier(constant_1.GEL_ELEMENT_BY_ID), t.identifier(constant_1.GEL_ELEMENT_BY_ID)));
            }
            if (source === constant_1.REDUX_PACKAGE_NAME || source === constant_1.MOBX_PACKAGE_NAME) {
                path.node.specifiers.forEach((s, index, specs) => {
                    if (s.local.name === 'Provider') {
                        specs.splice(index, 1);
                        specs.push(t.importSpecifier(t.identifier('setStore'), t.identifier('setStore')));
                    }
                });
            }
            path.traverse({
                ImportDefaultSpecifier(path) {
                    const name = path.node.local.name;
                    names.push(name);
                },
                ImportSpecifier(path) {
                    const name = path.node.imported.name;
                    names.push(name);
                    if (source === constant_1.TARO_PACKAGE_NAME && name === 'Component') {
                        path.node.local = t.identifier('__BaseComponent');
                    }
                }
            });
            componentSourceMap.set(source, names);
        }
    });
    if (!isImportTaro) {
        ast.program.body.unshift(t.importDeclaration([
            t.importDefaultSpecifier(t.identifier('Taro')),
            t.importSpecifier(t.identifier(constant_1.INTERNAL_SAFE_GET), t.identifier(constant_1.INTERNAL_SAFE_GET)),
            t.importSpecifier(t.identifier(constant_1.INTERNAL_GET_ORIGNAL), t.identifier(constant_1.INTERNAL_GET_ORIGNAL)),
            t.importSpecifier(t.identifier(constant_1.INTERNAL_INLINE_STYLE), t.identifier(constant_1.INTERNAL_INLINE_STYLE))
        ], t.stringLiteral('@tarojs/taro')));
    }
    if (!mainClass) {
        throw new Error('未找到 Taro.Component 的类定义');
    }
    mainClass.node.body.body.forEach(handleThirdPartyComponent);
    const storeBinding = mainClass.scope.getBinding(storeName);
    mainClass.scope.rename('Component', '__BaseComponent');
    if (storeBinding) {
        const statementPath = storeBinding.path.getStatementParent();
        if (statementPath) {
            ast.program.body.forEach((node, index, body) => {
                if (node === statementPath.node) {
                    body.splice(index + 1, 0, t.expressionStatement(t.callExpression(t.identifier('setStore'), [
                        t.identifier(storeName)
                    ])));
                }
            });
        }
    }
    resetTSClassProperty(mainClass.node.body.body);
    if (options.isApp) {
        renderMethod.replaceWith(t.classMethod('method', t.identifier('_createData'), [], t.blockStatement([])));
        return { ast };
    }
    result = new class_1.Transformer(mainClass, options.sourcePath, componentProperies).result;
    result.code = babel_generator_1.default(ast).code;
    result.ast = ast;
    const lessThanSignReg = new RegExp(constant_1.lessThanSignPlacehold, 'g');
    result.compressedTemplate = result.template;
    result.template = html_1.prettyPrint(result.template, {
        max_char: 0,
        unformatted: process.env.NODE_ENV === 'test' ? [] : ['text']
    });
    result.template = result.template.replace(lessThanSignReg, '<');
    result.imageSrcs = Array.from(imageSource);
    return result;
}
Example #13
0
File: rest.js Project: ANWSY/babel
    );

    // deopt shadowed functions as transforms like regenerator may try touch the allocation loop
    state.deopted = state.deopted || !!node.shadow;

    let start = t.numericLiteral(node.params.length);
    let key = scope.generateUidIdentifier("key");
    let len = scope.generateUidIdentifier("len");

    let arrKey = key;
    let arrLen = len;
    if (node.params.length) {
      // this method has additional params, so we need to subtract
      // the index of the current argument position from the
      // position in the array that we want to populate
      arrKey = t.binaryExpression("-", key, start);

      // we need to work out the size of the array that we're
      // going to store all the rest parameters
      //
      // we need to add a check to avoid constructing the array
      // with <0 if there are less arguments than params as it'll
      // cause an error
      arrLen = t.conditionalExpression(
        t.binaryExpression(">", len, start),
        t.binaryExpression("-", len, start),
        t.numericLiteral(0)
      );
    }

    let loop = buildRest({
 let op = fragment.reduce(function(acc, val) {
   return t.binaryExpression('+', acc, val); 
 });
Example #15
0
Ep.explodeExpression = function(path, ignoreResult) {
  let expr = path.node;
  if (expr) {
    t.assertExpression(expr);
  } else {
    return expr;
  }

  let self = this;
  let result; // Used optionally by several cases below.
  let after;

  function finish(expr) {
    t.assertExpression(expr);
    if (ignoreResult) {
      self.emit(expr);
    } else {
      return expr;
    }
  }

  // If the expression does not contain a leap, then we either emit the
  // expression as a standalone statement or return it whole.
  if (!meta.containsLeap(expr)) {
    return finish(expr);
  }

  // If any child contains a leap (such as a yield or labeled continue or
  // break statement), then any sibling subexpressions will almost
  // certainly have to be exploded in order to maintain the order of their
  // side effects relative to the leaping child(ren).
  let hasLeapingChildren = meta.containsLeap.onlyChildren(expr);

  // In order to save the rest of explodeExpression from a combinatorial
  // trainwreck of special cases, explodeViaTempVar is responsible for
  // deciding when a subexpression needs to be "exploded," which is my
  // very technical term for emitting the subexpression as an assignment
  // to a temporary variable and the substituting the temporary variable
  // for the original subexpression. Think of exploded view diagrams, not
  // Michael Bay movies. The point of exploding subexpressions is to
  // control the precise order in which the generated code realizes the
  // side effects of those subexpressions.
  function explodeViaTempVar(tempVar, childPath, ignoreChildResult) {
    assert.ok(
      !ignoreChildResult || !tempVar,
      "Ignoring the result of a child expression but forcing it to " +
        "be assigned to a temporary variable?"
    );

    let result = self.explodeExpression(childPath, ignoreChildResult);

    if (ignoreChildResult) {
      // Side effects already emitted above.

    } else if (tempVar || (hasLeapingChildren &&
                           !t.isLiteral(result))) {
      // If tempVar was provided, then the result will always be assigned
      // to it, even if the result does not otherwise need to be assigned
      // to a temporary variable.  When no tempVar is provided, we have
      // the flexibility to decide whether a temporary variable is really
      // necessary.  Unfortunately, in general, a temporary variable is
      // required whenever any child contains a yield expression, since it
      // is difficult to prove (at all, let alone efficiently) whether
      // this result would evaluate to the same value before and after the
      // yield (see #206).  One narrow case where we can prove it doesn't
      // matter (and thus we do not need a temporary variable) is when the
      // result in question is a Literal value.
      result = self.emitAssign(
        tempVar || self.makeTempVar(),
        result
      );
    }
    return result;
  }

  // If ignoreResult is true, then we must take full responsibility for
  // emitting the expression with all its side effects, and we should not
  // return a result.

  switch (expr.type) {
  case "MemberExpression":
    return finish(t.memberExpression(
      self.explodeExpression(path.get("object")),
      expr.computed
        ? explodeViaTempVar(null, path.get("property"))
        : expr.property,
      expr.computed
    ));

  case "CallExpression":
    let calleePath = path.get("callee");
    let argsPath = path.get("arguments");

    let newCallee;
    let newArgs = [];

    let hasLeapingArgs = false;
    argsPath.forEach(function(argPath) {
      hasLeapingArgs = hasLeapingArgs ||
        meta.containsLeap(argPath.node);
    });

    if (t.isMemberExpression(calleePath.node)) {
      if (hasLeapingArgs) {
        // If the arguments of the CallExpression contained any yield
        // expressions, then we need to be sure to evaluate the callee
        // before evaluating the arguments, but if the callee was a member
        // expression, then we must be careful that the object of the
        // member expression still gets bound to `this` for the call.

        let newObject = explodeViaTempVar(
          // Assign the exploded callee.object expression to a temporary
          // variable so that we can use it twice without reevaluating it.
          self.makeTempVar(),
          calleePath.get("object")
        );

        let newProperty = calleePath.node.computed
          ? explodeViaTempVar(null, calleePath.get("property"))
          : calleePath.node.property;

        newArgs.unshift(newObject);

        newCallee = t.memberExpression(
          t.memberExpression(
            newObject,
            newProperty,
            calleePath.node.computed
          ),
          t.identifier("call"),
          false
        );

      } else {
        newCallee = self.explodeExpression(calleePath);
      }

    } else {
      newCallee = self.explodeExpression(calleePath);

      if (t.isMemberExpression(newCallee)) {
        // If the callee was not previously a MemberExpression, then the
        // CallExpression was "unqualified," meaning its `this` object
        // should be the global object. If the exploded expression has
        // become a MemberExpression (e.g. a context property, probably a
        // temporary variable), then we need to force it to be unqualified
        // by using the (0, object.property)(...) trick; otherwise, it
        // will receive the object of the MemberExpression as its `this`
        // object.
        newCallee = t.sequenceExpression([
          t.numbericLiteral(0),
          newCallee
        ]);
      }
    }

    argsPath.forEach(function(argPath) {
      newArgs.push(explodeViaTempVar(null, argPath));
    });

    return finish(t.callExpression(
      newCallee,
      newArgs
    ));

  case "NewExpression":
    return finish(t.newExpression(
      explodeViaTempVar(null, path.get("callee")),
      path.get("arguments").map(function(argPath) {
        return explodeViaTempVar(null, argPath);
      })
    ));

  case "ObjectExpression":
    return finish(t.objectExpression(
      path.get("properties").map(function(propPath) {
        if (propPath.isObjectProperty()) {
          return t.objectProperty(
            propPath.node.key,
            explodeViaTempVar(null, propPath.get("value")),
            propPath.node.computed
          );
        } else {
          return propPath.node;
        }
      })
    ));

  case "ArrayExpression":
    return finish(t.arrayExpression(
      path.get("elements").map(function(elemPath) {
        return explodeViaTempVar(null, elemPath);
      })
    ));

  case "SequenceExpression":
    let lastIndex = expr.expressions.length - 1;

    path.get("expressions").forEach(function(exprPath) {
      if (exprPath.key === lastIndex) {
        result = self.explodeExpression(exprPath, ignoreResult);
      } else {
        self.explodeExpression(exprPath, true);
      }
    });

    return result;

  case "LogicalExpression":
    after = loc();

    if (!ignoreResult) {
      result = self.makeTempVar();
    }

    let left = explodeViaTempVar(result, path.get("left"));

    if (expr.operator === "&&") {
      self.jumpIfNot(left, after);
    } else {
      assert.strictEqual(expr.operator, "||");
      self.jumpIf(left, after);
    }

    explodeViaTempVar(result, path.get("right"), ignoreResult);

    self.mark(after);

    return result;

  case "ConditionalExpression":
    let elseLoc = loc();
    after = loc();
    let test = self.explodeExpression(path.get("test"));

    self.jumpIfNot(test, elseLoc);

    if (!ignoreResult) {
      result = self.makeTempVar();
    }

    explodeViaTempVar(result, path.get("consequent"), ignoreResult);
    self.jump(after);

    self.mark(elseLoc);
    explodeViaTempVar(result, path.get("alternate"), ignoreResult);

    self.mark(after);

    return result;

  case "UnaryExpression":
    return finish(t.unaryExpression(
      expr.operator,
      // Can't (and don't need to) break up the syntax of the argument.
      // Think about delete a[b].
      self.explodeExpression(path.get("argument")),
      !!expr.prefix
    ));

  case "BinaryExpression":
    return finish(t.binaryExpression(
      expr.operator,
      explodeViaTempVar(null, path.get("left")),
      explodeViaTempVar(null, path.get("right"))
    ));

  case "AssignmentExpression":
    return finish(t.assignmentExpression(
      expr.operator,
      self.explodeExpression(path.get("left")),
      self.explodeExpression(path.get("right"))
    ));

  case "UpdateExpression":
    return finish(t.updateExpression(
      expr.operator,
      self.explodeExpression(path.get("argument")),
      expr.prefix
    ));

  case "YieldExpression":
    after = loc();
    let arg = expr.argument && self.explodeExpression(path.get("argument"));

    if (arg && expr.delegate) {
      let result = self.makeTempVar();

      self.emit(t.returnStatement(t.callExpression(
        self.contextProperty("delegateYield"), [
          arg,
          t.stringLiteral(result.property.name),
          after
        ]
      )));

      self.mark(after);

      return result;
    }

    self.emitAssign(self.contextProperty("next"), after);
    self.emit(t.returnStatement(arg || null));
    self.mark(after);

    return self.contextProperty("sent");

  default:
    throw new Error(
      "unknown Expression of type " +
        JSON.stringify(expr.type));
  }
};
Example #16
0
export default function () {
  let REASSIGN_REMAP_SKIP = Symbol();

  let reassignmentVisitor = {
    ReferencedIdentifier(path) {
      let name = path.node.name;
      let remap = this.remaps[name];
      if (!remap) return;

      // redeclared in this scope
      if (this.scope.getBinding(name) !== path.scope.getBinding(name)) return;

      if (path.parentPath.isCallExpression({ callee: path.node })) {
        path.replaceWith(t.sequenceExpression([t.numericLiteral(0), remap]));
      } else {
        path.replaceWith(remap);
      }
      this.requeueInParent(path);
    },

    AssignmentExpression(path) {
      let node = path.node;
      if (node[REASSIGN_REMAP_SKIP]) return;

      let left = path.get("left");
      if (!left.isIdentifier()) return;

      let name = left.node.name;
      let exports = this.exports[name];
      if (!exports) return;

      // redeclared in this scope
      if (this.scope.getBinding(name) !== path.scope.getBinding(name)) return;

      node[REASSIGN_REMAP_SKIP] = true;

      for (let reid of exports) {
        node = buildExportsAssignment(reid, node).expression;
      }

      path.replaceWith(node);
      this.requeueInParent(path);
    },

    UpdateExpression(path) {
      let arg = path.get("argument");
      if (!arg.isIdentifier()) return;

      let name = arg.node.name;
      let exports = this.exports[name];
      if (!exports) return;

      // redeclared in this scope
      if (this.scope.getBinding(name) !== path.scope.getBinding(name)) return;

      let node = t.assignmentExpression(path.node.operator[0] + "=", arg.node, t.numericLiteral(1));

      if ((path.parentPath.isExpressionStatement() && !path.isCompletionRecord()) || path.node.prefix) {
        path.replaceWith(node);
        this.requeueInParent(path);
        return;
      }

      let nodes = [];
      nodes.push(node);

      let operator;
      if (path.node.operator === "--") {
        operator = "+";
      } else { // "++"
        operator = "-";
      }
      nodes.push(t.binaryExpression(operator, arg.node, t.numericLiteral(1)));

      let newPaths = path.replaceWithMultiple(t.sequenceExpression(nodes));
      for (const newPath of newPaths) this.requeueInParent(newPath);
    }
  };

  return {
    inherits: require("babel-plugin-transform-strict-mode"),

    visitor: {
      ThisExpression(path, state) {
        // If other plugins run after this plugin's Program#exit handler, we allow them to
        // insert top-level `this` values. This allows the AMD and UMD plugins to
        // function properly.
        if (this.ranCommonJS) return;

        if (
          state.opts.allowTopLevelThis !== true &&
          !path.findParent((path) => !path.is("shadow") &&
          THIS_BREAK_KEYS.indexOf(path.type) >= 0)
        ) {
          path.replaceWith(t.identifier("undefined"));
        }
      },

      Program: {
        exit(path) {
          this.ranCommonJS = true;

          let strict = !!this.opts.strict;

          let { scope } = path;

          // rename these commonjs variables if they're declared in the file
          scope.rename("module");
          scope.rename("exports");
          scope.rename("require");

          let hasExports = false;
          let hasImports = false;

          let body: Array<Object> = path.get("body");
          let imports = Object.create(null);
          let exports = Object.create(null);

          let nonHoistedExportNames = Object.create(null);

          let topNodes = [];
          let remaps = Object.create(null);

          let requires = Object.create(null);

          function addRequire(source, blockHoist) {
            let cached = requires[source];
            if (cached) return cached;

            let ref = path.scope.generateUidIdentifier(basename(source, extname(source)));

            let varDecl = t.variableDeclaration("var", [
              t.variableDeclarator(ref, buildRequire(
                t.stringLiteral(source)
              ).expression)
            ]);

            if (typeof blockHoist === "number" && blockHoist > 0) {
              varDecl._blockHoist = blockHoist;
            }

            topNodes.push(varDecl);

            return requires[source] = ref;
          }

          function addTo(obj, key, arr) {
            let existing = obj[key] || [];
            obj[key] = existing.concat(arr);
          }

          for (let path of body) {
            if (path.isExportDeclaration()) {
              hasExports = true;

              let specifiers = [].concat(path.get("declaration"), path.get("specifiers"));
              for (let specifier of specifiers) {
                let ids = specifier.getBindingIdentifiers();
                if (ids.__esModule) {
                  throw specifier.buildCodeFrameError("Illegal export \"__esModule\"");
                }
              }
            }

            if (path.isImportDeclaration()) {
              hasImports = true;

              let key = path.node.source.value;
              let importsEntry = imports[key] || {
                specifiers: [],
                maxBlockHoist: 0
              };

              importsEntry.specifiers.push(...path.node.specifiers);

              if (typeof path.node._blockHoist === "number") {
                importsEntry.maxBlockHoist = Math.max(
                  path.node._blockHoist,
                  importsEntry.maxBlockHoist
                );
              }

              imports[key] = importsEntry;

              path.remove();
            } else if (path.isExportDefaultDeclaration()) {
              let declaration = path.get("declaration");
              if (declaration.isFunctionDeclaration()) {
                let id = declaration.node.id;
                let defNode = t.identifier("default");
                if (id) {
                  addTo(exports, id.name, defNode);
                  topNodes.push(buildExportsAssignment(defNode, id));
                  path.replaceWith(declaration.node);
                } else {
                  topNodes.push(buildExportsAssignment(defNode, t.toExpression(declaration.node)));
                  path.remove();
                }
              } else if (declaration.isClassDeclaration()) {
                let id = declaration.node.id;
                let defNode = t.identifier("default");
                if (id) {
                  addTo(exports, id.name, defNode);
                  path.replaceWithMultiple([
                    declaration.node,
                    buildExportsAssignment(defNode, id)
                  ]);
                } else {
                  path.replaceWith(buildExportsAssignment(defNode, t.toExpression(declaration.node)));
                }
              } else {
                path.replaceWith(buildExportsAssignment(t.identifier("default"), declaration.node));
              }
            } else if (path.isExportNamedDeclaration()) {
              let declaration = path.get("declaration");
              if (declaration.node) {
                if (declaration.isFunctionDeclaration()) {
                  let id = declaration.node.id;
                  addTo(exports, id.name, id);
                  topNodes.push(buildExportsAssignment(id, id));
                  path.replaceWith(declaration.node);
                } else if (declaration.isClassDeclaration()) {
                  let id = declaration.node.id;
                  addTo(exports, id.name, id);
                  path.replaceWithMultiple([
                    declaration.node,
                    buildExportsAssignment(id, id)
                  ]);
                  nonHoistedExportNames[id.name] = true;
                } else if (declaration.isVariableDeclaration()) {
                  let declarators = declaration.get("declarations");
                  for (let decl of declarators) {
                    let id = decl.get("id");

                    let init = decl.get("init");
                    if (!init.node) init.replaceWith(t.identifier("undefined"));

                    if (id.isIdentifier()) {
                      addTo(exports, id.node.name, id.node);
                      init.replaceWith(buildExportsAssignment(id.node, init.node).expression);
                      nonHoistedExportNames[id.node.name] = true;
                    } else {
                      // todo
                    }
                  }
                  path.replaceWith(declaration.node);
                }
                continue;
              }

              let specifiers = path.get("specifiers");
              if (specifiers.length) {
                let nodes = [];
                let source = path.node.source;
                if (source) {
                  let ref = addRequire(source.value, path.node._blockHoist);

                  for (let specifier of specifiers) {
                    if (specifier.isExportNamespaceSpecifier()) {
                      // todo
                    } else if (specifier.isExportDefaultSpecifier()) {
                      // todo
                    } else if (specifier.isExportSpecifier()) {
                      if (specifier.node.local.name === "default") {
                        topNodes.push(buildExportsFrom(t.stringLiteral(specifier.node.exported.name), t.memberExpression(t.callExpression(this.addHelper("interopRequireDefault"), [ref]), specifier.node.local)));
                      } else {
                        topNodes.push(buildExportsFrom(t.stringLiteral(specifier.node.exported.name), t.memberExpression(ref, specifier.node.local)));
                      }
                      nonHoistedExportNames[specifier.node.exported.name] = true;
                    }
                  }
                } else {
                  for (let specifier of specifiers) {
                    if (specifier.isExportSpecifier()) {
                      addTo(exports, specifier.node.local.name, specifier.node.exported);
                      nonHoistedExportNames[specifier.node.exported.name] = true;
                      nodes.push(buildExportsAssignment(specifier.node.exported, specifier.node.local));
                    }
                  }
                }
                path.replaceWithMultiple(nodes);
              }
            } else if (path.isExportAllDeclaration()) {
              topNodes.push(buildExportAll({
                KEY: path.scope.generateUidIdentifier("key"),
                OBJECT: addRequire(path.node.source.value, path.node._blockHoist)
              }));
              path.remove();
            }
          }

          for (let source in imports) {
            let {specifiers, maxBlockHoist} = imports[source];
            if (specifiers.length) {
              let uid = addRequire(source, maxBlockHoist);

              let wildcard;

              for (let i = 0; i < specifiers.length; i++) {
                let specifier = specifiers[i];
                if (t.isImportNamespaceSpecifier(specifier)) {
                  if (strict) {
                    remaps[specifier.local.name] = uid;
                  } else {
                    const varDecl = t.variableDeclaration("var", [
                      t.variableDeclarator(
                        specifier.local,
                        t.callExpression(
                          this.addHelper("interopRequireWildcard"),
                          [uid]
                        )
                      )
                    ]);

                    if (maxBlockHoist > 0) {
                      varDecl._blockHoist = maxBlockHoist;
                    }

                    topNodes.push(varDecl);
                  }
                  wildcard = specifier.local;
                } else if (t.isImportDefaultSpecifier(specifier)) {
                  specifiers[i] = t.importSpecifier(specifier.local, t.identifier("default"));
                }
              }

              for (let specifier of specifiers) {
                if (t.isImportSpecifier(specifier)) {
                  let target = uid;
                  if (specifier.imported.name === "default") {
                    if (wildcard) {
                      target = wildcard;
                    } else {
                      target = wildcard = path.scope.generateUidIdentifier(uid.name);
                      const varDecl = t.variableDeclaration("var", [
                        t.variableDeclarator(
                          target,
                          t.callExpression(
                            this.addHelper("interopRequireDefault"),
                            [uid]
                          )
                        )
                      ]);

                      if (maxBlockHoist > 0) {
                        varDecl._blockHoist = maxBlockHoist;
                      }

                      topNodes.push(varDecl);
                    }
                  }
                  remaps[specifier.local.name] = t.memberExpression(target, t.cloneWithoutLoc(specifier.imported));
                }
              }
            } else {
              // bare import
              topNodes.push(buildRequire(t.stringLiteral(source)));
            }
          }

          if (hasImports && Object.keys(nonHoistedExportNames).length) {
            let hoistedExportsNode = t.identifier("undefined");

            for (let name in nonHoistedExportNames) {
              hoistedExportsNode = buildExportsAssignment(t.identifier(name), hoistedExportsNode).expression;
            }

            const node = t.expressionStatement(hoistedExportsNode);
            node._blockHoist = 3;

            topNodes.unshift(node);
          }

          // add __esModule declaration if this file has any exports
          if (hasExports && !strict) {
            let buildTemplate = buildExportsModuleDeclaration;
            if (this.opts.loose) buildTemplate = buildLooseExportsModuleDeclaration;

            const declar = buildTemplate();
            declar._blockHoist = 3;

            topNodes.unshift(declar);
          }

          path.unshiftContainer("body", topNodes);
          path.traverse(reassignmentVisitor, {
            remaps,
            scope,
            exports,
            requeueInParent: (newPath) => path.requeue(newPath),
          });
        }
      }
    }
  };
}
Example #17
0
  visitMixin: function(mixin){
    var ast = [];
    var self = this;
    var name = 'pug_mixins[';
    var args = mixin.args || '';
    var block = mixin.block;
    var attrs = mixin.attrs;
    var attrsBlocks = this.attributeBlocks(mixin.attributeBlocks);
    var pp = this.pp;
    var dynamic = mixin.name[0]==='#';
    var key = mixin.name;
    if (dynamic) this.dynamicMixins = true;
    name += (dynamic ? mixin.name.substr(2,mixin.name.length-3):'"'+mixin.name+'"')+']';
    var mixinName = dynamic ? (mixin.astName || this.parseExpr(mixin.name.substr(2,mixin.name.length-3))): t.stringLiteral(mixin.name);
    this.mixins[key] = this.mixins[key] || {used: false, instances: []};

    // mixin invocation
    if (mixin.call) {
      this.mixins[key].used = true;
      if (pp) {
        ast.push(t.expressionStatement(t.callExpression(
          t.memberExpression(t.identifier('pug_indent'), t.identifier('push')),
          [t.stringLiteral(Array(this.indents + 1).join(pp))]
        )))
      }
      if (block || attrs.length || attrsBlocks.length) {

        var astArgs = []
        ast.push(
          t.expressionStatement(this.wrapCallExpression(t.callExpression(
            t.memberExpression(
              t.memberExpression(t.identifier('pug_mixins'), mixinName, true),
              t.identifier("call")
            ),
            astArgs
          )))
        );

        var astObj, astKey;
        if (block || attrsBlocks.length || attrs.length) {
          astKey = [];
          astObj = t.objectExpression(astKey);
          astArgs.push(astObj);
        }

        if (block) {
          var astFunc = [];
        
          // Render block with no indents, dynamically added when rendered
          this.parentIndents++;
          var _indents = this.indents;
          this.indents = 0;
          push.apply(astFunc, this.visit(mixin.block, mixin));
          this.indents = _indents;
          this.parentIndents--;

          astKey.push(t.objectProperty(
            t.identifier('block'),
            t.functionExpression(
              null,
              [],
              t.blockStatement(astFunc),
              this.useGenerators
            )
          ));
 
        }

        if (attrsBlocks.length) {
          if (attrs.length) {
            var val = this.attrs(attrs);
            attrsBlocks.unshift(val);
          }
          if (attrsBlocks.length > 1) {
            astKey.push(t.objectProperty(
              t.identifier('attributes'),
              t.callExpression(
                this.runtime('merge', true),
                attrsBlocks.map(function(b) { return self.parseExpr(b) })
              )
            ));
          } else {
            astKey.push(t.objectProperty(
              t.identifier('attributes'),
              this.parseExpr(attrsBlocks[0])
            ));
          }
        } else if (attrs.length) {
          var val = this.attrs(attrs);
          astKey.push(t.objectProperty(
            t.identifier('attributes'),
            this.parseExpr(val)
          ));
        }

        if (args) { 
          args = args ? args.split(',') : [];
          Array.prototype.push.apply(astArgs, mixin.astArgs || this.parseArgs(args) )
        }

      } else {
        var astArgs = mixin.astArgs || this.parseArgs(args);
        ast.push(t.expressionStatement(this.wrapCallExpression(t.callExpression(
          t.memberExpression(t.identifier('pug_mixins'), mixinName, true),
          astArgs
        ))));
      }
      if (pp) {
        ast.push(t.expressionStatement(t.callExpression(
          t.memberExpression(t.identifier('pug_indent'), t.identifier('pop')),
          []
        )))
 
      }
    }
    // mixin definition
    else {
      args = args ? args.split(',') : [];
      var rest;
      if (args.length && /^\.\.\./.test(args[args.length - 1].trim())) {
        rest = args.pop().trim().replace(/^\.\.\./, '');
      }
      var astArgs = args.map(function(arg) { return t.identifier(arg.trim())})
      // we need use pug_interp here for v8: https://code.google.com/p/v8/issues/detail?id=4165
      // once fixed, use this: this.buf.push(name + ' = function(' + args.join(',') + '){');
      var astMixin = [];

      astMixin.push(
        t.variableDeclaration('var', [
          t.variableDeclarator(
            t.identifier('block'),
            t.logicalExpression('&&', t.thisExpression(), t.memberExpression(t.thisExpression(), t.identifier('block')))
          ),
          t.variableDeclarator(
            t.identifier('attributes'),
            t.logicalExpression('||',
              t.logicalExpression('&&', t.thisExpression(), t.memberExpression(t.thisExpression(), t.identifier('attributes'))),
              t.objectExpression([])
            )
          )
        ])
      )

      if (rest) {
        astMixin.push(
          t.variableDeclaration('var', [
            t.variableDeclarator(
              t.identifier(rest),
              t.arrayExpression([])
            )
          ])
        )
        astMixin.push(
          t.forStatement(
            t.assignmentExpression('=', t.identifier('pug_interp'), t.numericLiteral(args.length)),
            t.binaryExpression('<', t.identifier('pug_interp'), t.memberExpression(t.identifier('arguments'), t.identifier('length'))),
            t.updateExpression('++', t.identifier('pug_interp'), false),
            t.expressionStatement(
              t.callExpression(
                t.memberExpression(t.identifier(rest), t.identifier('push')),
                [t.memberExpression(t.identifier('arguments'), t.identifier('pug_interp'), true)]
              )
            )
          )
        )
      }

      this.parentIndents++;
      push.apply(astMixin, this.visit(block, mixin));
      this.parentIndents--;


      var mixinStmt = 
        t.expressionStatement(
          t.assignmentExpression(
            '=',
            t.memberExpression(t.identifier('pug_mixins'), mixinName, true),
            t.assignmentExpression(
              '=',
              t.identifier('pug_interp'),
              t.functionExpression(
                null,
                astArgs,
                t.blockStatement(astMixin),
                this.useGenerators
              )
            )
          )
        );
      ast.push(mixinStmt);
 


      this.mixins[key].instances.push({stmt: mixinStmt});
    }
    return ast;
  },
Example #18
0
import * as babylon from 'babylon'
import traverse from 'babel-traverse'
import generate from 'babel-generator'
import * as t from 'babel-types'


const code = `
import a from 'b'
n === 3
`

const ast = babylon.parse(code, {
  sourceType: 'module'
})

const visitor = {
  BinaryExpression(path) {
    console.log((path.node))
    path.replaceWith(t.binaryExpression('**', t.numericLiteral(3), t.numericLiteral(4)))
  }
}

traverse(ast, visitor)

let generated = generate(ast, null, code)
console.log(generated.code)
Example #19
0
  visitEach: function(each){
    var ast = [];
    var indexVarName = each.key || 'pug_index' + this.eachCount;
    this.eachCount++;


    var body =  [
                  t.variableDeclaration('var', [
                    t.variableDeclarator(t.identifier('$$obj'), each.astObj || this.parseExpr(each.obj))
                  ])
                ]

    var func =  t.expressionStatement(
                  this.wrapCallExpression(t.callExpression(
                    t.memberExpression(
                      t.functionExpression(
                        null,
                        [],
                        t.blockStatement(body),
                        this.useGenerators
                      ),
                      t.identifier('call')
                    )
                    ,[t.thisExpression()]
                  ))
                )
    ast.push(func)


      var blockEach = [
        t.variableDeclaration('var', [
            t.variableDeclarator(t.identifier(each.val), t.memberExpression(t.identifier('$$obj'), t.identifier(indexVarName), true) )
        ])
      ];
      var blockAlt = [];
 
      push.apply(blockEach, this.visit(each.block, each));
      var arrayLoop = 
          t.blockStatement([t.forStatement(
            t.variableDeclaration('var', [
              t.variableDeclarator(t.identifier(indexVarName), t.numericLiteral(0)),
              t.variableDeclarator(t.identifier('$$l'), t.memberExpression(t.identifier('$$obj'), t.identifier('length')))
            ]),
            t.binaryExpression('<', t.identifier(indexVarName), t.identifier('$$l')),
            t.updateExpression('++', t.identifier(indexVarName), false),
            t.blockStatement(blockEach)
          )]);


      var blockObj = [
        t.expressionStatement(t.updateExpression('++', t.identifier('$$l'), false)),
        t.variableDeclaration('var', [
          t.variableDeclarator(t.identifier(each.val), t.memberExpression(t.identifier('$$obj'), t.identifier(indexVarName), true) )
        ])
      ]
      var blockObjAlt = [];

      push.apply(blockObj, this.visit(each.block, each));
      var objectLoop = t.blockStatement([
        t.variableDeclaration('var', [
          t.variableDeclarator(t.identifier('$$l'), t.numericLiteral(0))
        ]),
        t.forInStatement(
          t.variableDeclaration('var', [
            t.variableDeclarator(t.identifier(indexVarName))
          ]),
          t.identifier('$$obj'),
          t.blockStatement(blockObj)
        )
      ])



    if (each.alternate) {
      push.apply(blockAlt, this.visit(each.alternate, each));
      arrayLoop = t.ifStatement(
        t.memberExpression(t.identifier('$$obj'), t.identifier('length')),
        arrayLoop,
        t.blockStatement(blockAlt)
      );
   }


    if (each.alternate) {
      push.apply(blockObjAlt, this.visit(each.alternate, each));
      objectLoop.body.push(t.ifStatement(
            t.binaryExpression('===', t.identifier('$$l'), t.numericLiteral(0)),
            t.blockStatement(blockObjAlt)
      ))
    }

    var it = t.ifStatement(
        t.binaryExpression('==', t.stringLiteral('number'), t.unaryExpression('typeof', t.memberExpression(t.identifier('$$obj'), t.identifier('length')))),
        arrayLoop, objectLoop)
    body.push(it);

    return ast;

  },
Example #20
0
      const classNamePropValueForReals = classNameObjects.reduce((acc, val) => {
        if (!acc) {
          if (
            // pass conditional expressions through
            t.isConditionalExpression(val) ||
            // pass non-null literals through
            (t.isLiteral(val) && val.value !== null)
          ) {
            return val;
          }
          return t.logicalExpression('||', val, t.stringLiteral(''));
        }

        const accIsString = t.isLiteral(acc) && typeof acc.value === 'string';

        let inner;
        if (t.isLiteral(val)) {
          if (typeof val.value === 'string') {
            if (accIsString) {
              // join adjacent string literals
              return t.stringLiteral(`${acc.value} ${val.value}`);
            }
            inner = t.stringLiteral(` ${val.value}`);
          } else {
            inner = t.binaryExpression('+', t.stringLiteral(' '), val);
          }
        } else if (
          t.isConditionalExpression(val) ||
          t.isBinaryExpression(val)
        ) {
          if (accIsString) {
            return t.binaryExpression(
              '+',
              t.stringLiteral(`${acc.value} `),
              val
            );
          }
          inner = t.binaryExpression('+', t.stringLiteral(' '), val);
        } else if (t.isIdentifier(val) || t.isMemberExpression(val)) {
          // identifiers and member expressions make for reasonable ternaries
          inner = t.conditionalExpression(
            val,
            t.binaryExpression('+', t.stringLiteral(' '), val),
            t.stringLiteral('')
          );
        } else {
          if (accIsString) {
            return t.binaryExpression(
              '+',
              t.stringLiteral(`${acc.value} `),
              t.logicalExpression('||', val, t.stringLiteral(''))
            );
          }
          // use a logical expression for more complex prop values
          inner = t.binaryExpression(
            '+',
            t.stringLiteral(' '),
            t.logicalExpression('||', val, t.stringLiteral(''))
          );
        }
        return t.binaryExpression('+', acc, inner);
      }, null);
Example #21
0
Ep.explodeStatement = function(path, labelId) {
  let stmt = path.node;
  let self = this;
  let before, after, head;

  t.assertStatement(stmt);

  if (labelId) {
    t.assertIdentifier(labelId);
  } else {
    labelId = null;
  }

  // Explode BlockStatement nodes even if they do not contain a yield,
  // because we don't want or need the curly braces.
  if (t.isBlockStatement(stmt)) {
    path.get("body").forEach(function (path) {
      self.explodeStatement(path);
    });
    return;
  }

  if (!meta.containsLeap(stmt)) {
    // Technically we should be able to avoid emitting the statement
    // altogether if !meta.hasSideEffects(stmt), but that leads to
    // confusing generated code (for instance, `while (true) {}` just
    // disappears) and is probably a more appropriate job for a dedicated
    // dead code elimination pass.
    self.emit(stmt);
    return;
  }

  switch (stmt.type) {
  case "ExpressionStatement":
    self.explodeExpression(path.get("expression"), true);
    break;

  case "LabeledStatement":
    after = loc();

    // Did you know you can break from any labeled block statement or
    // control structure? Well, you can! Note: when a labeled loop is
    // encountered, the leap.LabeledEntry created here will immediately
    // enclose a leap.LoopEntry on the leap manager's stack, and both
    // entries will have the same label. Though this works just fine, it
    // may seem a bit redundant. In theory, we could check here to
    // determine if stmt knows how to handle its own label; for example,
    // stmt happens to be a WhileStatement and so we know it's going to
    // establish its own LoopEntry when we explode it (below). Then this
    // LabeledEntry would be unnecessary. Alternatively, we might be
    // tempted not to pass stmt.label down into self.explodeStatement,
    // because we've handled the label here, but that's a mistake because
    // labeled loops may contain labeled continue statements, which is not
    // something we can handle in this generic case. All in all, I think a
    // little redundancy greatly simplifies the logic of this case, since
    // it's clear that we handle all possible LabeledStatements correctly
    // here, regardless of whether they interact with the leap manager
    // themselves. Also remember that labels and break/continue-to-label
    // statements are rare, and all of this logic happens at transform
    // time, so it has no additional runtime cost.
    self.leapManager.withEntry(
      new leap.LabeledEntry(after, stmt.label),
      function() {
        self.explodeStatement(path.get("body"), stmt.label);
      }
    );

    self.mark(after);

    break;

  case "WhileStatement":
    before = loc();
    after = loc();

    self.mark(before);
    self.jumpIfNot(self.explodeExpression(path.get("test")), after);
    self.leapManager.withEntry(
      new leap.LoopEntry(after, before, labelId),
      function() { self.explodeStatement(path.get("body")); }
    );
    self.jump(before);
    self.mark(after);

    break;

  case "DoWhileStatement":
    let first = loc();
    let test = loc();
    after = loc();

    self.mark(first);
    self.leapManager.withEntry(
      new leap.LoopEntry(after, test, labelId),
      function() { self.explode(path.get("body")); }
    );
    self.mark(test);
    self.jumpIf(self.explodeExpression(path.get("test")), first);
    self.mark(after);

    break;

  case "ForStatement":
    head = loc();
    let update = loc();
    after = loc();

    if (stmt.init) {
      // We pass true here to indicate that if stmt.init is an expression
      // then we do not care about its result.
      self.explode(path.get("init"), true);
    }

    self.mark(head);

    if (stmt.test) {
      self.jumpIfNot(self.explodeExpression(path.get("test")), after);
    } else {
      // No test means continue unconditionally.
    }

    self.leapManager.withEntry(
      new leap.LoopEntry(after, update, labelId),
      function() { self.explodeStatement(path.get("body")); }
    );

    self.mark(update);

    if (stmt.update) {
      // We pass true here to indicate that if stmt.update is an
      // expression then we do not care about its result.
      self.explode(path.get("update"), true);
    }

    self.jump(head);

    self.mark(after);

    break;

  case "TypeCastExpression":
    return self.explodeExpression(path.get("expression"));

  case "ForInStatement":
    head = loc();
    after = loc();

    let keyIterNextFn = self.makeTempVar();
    self.emitAssign(
      keyIterNextFn,
      t.callExpression(
        util.runtimeProperty("keys"),
        [self.explodeExpression(path.get("right"))]
      )
    );

    self.mark(head);

    let keyInfoTmpVar = self.makeTempVar();
    self.jumpIf(
      t.memberExpression(
        t.assignmentExpression(
          "=",
          keyInfoTmpVar,
          t.callExpression(keyIterNextFn, [])
        ),
        t.identifier("done"),
        false
      ),
      after
    );

    self.emitAssign(
      stmt.left,
      t.memberExpression(
        keyInfoTmpVar,
        t.identifier("value"),
        false
      )
    );

    self.leapManager.withEntry(
      new leap.LoopEntry(after, head, labelId),
      function() { self.explodeStatement(path.get("body")); }
    );

    self.jump(head);

    self.mark(after);

    break;

  case "BreakStatement":
    self.emitAbruptCompletion({
      type: "break",
      target: self.leapManager.getBreakLoc(stmt.label)
    });

    break;

  case "ContinueStatement":
    self.emitAbruptCompletion({
      type: "continue",
      target: self.leapManager.getContinueLoc(stmt.label)
    });

    break;

  case "SwitchStatement":
    // Always save the discriminant into a temporary variable in case the
    // test expressions overwrite values like context.sent.
    let disc = self.emitAssign(
      self.makeTempVar(),
      self.explodeExpression(path.get("discriminant"))
    );

    after = loc();
    let defaultLoc = loc();
    let condition = defaultLoc;
    let caseLocs = [];

    // If there are no cases, .cases might be undefined.
    let cases = stmt.cases || [];

    for (let i = cases.length - 1; i >= 0; --i) {
      let c = cases[i];
      t.assertSwitchCase(c);

      if (c.test) {
        condition = t.conditionalExpression(
          t.binaryExpression("===", disc, c.test),
          caseLocs[i] = loc(),
          condition
        );
      } else {
        caseLocs[i] = defaultLoc;
      }
    }

    let discriminant = path.get("discriminant");
    discriminant.replaceWith(condition);
    self.jump(self.explodeExpression(discriminant));

    self.leapManager.withEntry(
      new leap.SwitchEntry(after),
      function() {
        path.get("cases").forEach(function(casePath) {
          let i = casePath.key;
          self.mark(caseLocs[i]);

          casePath.get("consequent").forEach(function (path) {
            self.explodeStatement(path);
          });
        });
      }
    );

    self.mark(after);
    if (defaultLoc.value === -1) {
      self.mark(defaultLoc);
      assert.strictEqual(after.value, defaultLoc.value);
    }

    break;

  case "IfStatement":
    let elseLoc = stmt.alternate && loc();
    after = loc();

    self.jumpIfNot(
      self.explodeExpression(path.get("test")),
      elseLoc || after
    );

    self.explodeStatement(path.get("consequent"));

    if (elseLoc) {
      self.jump(after);
      self.mark(elseLoc);
      self.explodeStatement(path.get("alternate"));
    }

    self.mark(after);

    break;

  case "ReturnStatement":
    self.emitAbruptCompletion({
      type: "return",
      value: self.explodeExpression(path.get("argument"))
    });

    break;

  case "WithStatement":
    throw new Error("WithStatement not supported in generator functions.");

  case "TryStatement":
    after = loc();

    let handler = stmt.handler;

    let catchLoc = handler && loc();
    let catchEntry = catchLoc && new leap.CatchEntry(
      catchLoc,
      handler.param
    );

    let finallyLoc = stmt.finalizer && loc();
    let finallyEntry = finallyLoc &&
      new leap.FinallyEntry(finallyLoc, after);

    let tryEntry = new leap.TryEntry(
      self.getUnmarkedCurrentLoc(),
      catchEntry,
      finallyEntry
    );

    self.tryEntries.push(tryEntry);
    self.updateContextPrevLoc(tryEntry.firstLoc);

    self.leapManager.withEntry(tryEntry, function() {
      self.explodeStatement(path.get("block"));

      if (catchLoc) {
        if (finallyLoc) {
          // If we have both a catch block and a finally block, then
          // because we emit the catch block first, we need to jump over
          // it to the finally block.
          self.jump(finallyLoc);

        } else {
          // If there is no finally block, then we need to jump over the
          // catch block to the fall-through location.
          self.jump(after);
        }

        self.updateContextPrevLoc(self.mark(catchLoc));

        let bodyPath = path.get("handler.body");
        let safeParam = self.makeTempVar();
        self.clearPendingException(tryEntry.firstLoc, safeParam);

        bodyPath.traverse(catchParamVisitor, {
          safeParam: safeParam,
          catchParamName: handler.param.name
        });

        self.leapManager.withEntry(catchEntry, function() {
          self.explodeStatement(bodyPath);
        });
      }

      if (finallyLoc) {
        self.updateContextPrevLoc(self.mark(finallyLoc));

        self.leapManager.withEntry(finallyEntry, function() {
          self.explodeStatement(path.get("finalizer"));
        });

        self.emit(t.returnStatement(t.callExpression(
          self.contextProperty("finish"),
          [finallyEntry.firstLoc]
        )));
      }
    });

    self.mark(after);

    break;

  case "ThrowStatement":
    self.emit(t.throwStatement(
      self.explodeExpression(path.get("argument"))
    ));

    break;

  default:
    throw new Error(
      "unknown Statement of type " +
        JSON.stringify(stmt.type));
  }
};