在使用本方法前，必须初始化AopClient且传入公私钥参数。
公钥是否是读取字符串还是读取文件，是根据初始化传入的值判断的。
556691
public function encryptAndSign($bizContent, $rsaPublicKeyPem, $rsaPrivateKeyPem, $charset, $isEncrypt, $isSign, $signType='RSA') {
		// 加密，并签名
		if ($isEncrypt && $isSign) {
			$encrypted = $this->rsaEncrypt($bizContent, $rsaPublicKeyPem, $charset);
			$sign = $this->sign($encrypted, $signType);
			$response = "<?xml version=\"1.0\" encoding=\"$charset\"?><alipay><response>$encrypted</response><encryption_type>RSA</encryption_type><sign>$sign</sign><sign_type>$signType</sign_type></alipay>";
			return $response;
		}
		// 加密，不签名
		if ($isEncrypt && (!$isSign)) {
			$encrypted = $this->rsaEncrypt($bizContent, $rsaPublicKeyPem, $charset);
			$response = "<?xml version=\"1.0\" encoding=\"$charset\"?><alipay><response>$encrypted</response><encryption_type>$signType</encryption_type></alipay>";
			return $response;
		}
		// 不加密，但签名
		if ((!$isEncrypt) && $isSign) {
			$sign = $this->sign($bizContent, $signType);
			$response = "<?xml version=\"1.0\" encoding=\"$charset\"?><alipay><response>$bizContent</response><sign>$sign</sign><sign_type>$signType</sign_type></alipay>";
			return $response;
		}
		// 不加密，不签名
		$response = "<?xml version=\"1.0\" encoding=\"$charset\"?>$bizContent";
		return $response;
	}
860312
private String genRequestPath() {
		//首先解析方法上的路径
		String[] httpMthodAndPath = getHttpMethodAndPath(this.method);
		this.httpMethod = httpMthodAndPath[0];
		String methodPath = httpMthodAndPath[1];
		
		if(StrUtil.isNotEmpty(methodPath) && methodPath.startsWith(StrUtil.SLASH)){
			return methodPath;
		}else{
			httpMthodAndPath = getHttpMethodAndPath(this.action.getClass());
			if(StrUtil.isBlank(this.httpMethod)){
				httpMethod = httpMthodAndPath[0];
			}
			final String actionPath = httpMthodAndPath[1];
			//Action路径
			return StrUtil.format("{}/{}", fixFirstSlash(actionPath), methodPath);
		}
	}
317167
private void uploadThumbImage(StorageNode client, InputStream inputStream,
                                  String masterFilename, FastImageFile fastImageFile) {
        ByteArrayInputStream thumbImageStream = null;
        ThumbImage thumbImage = fastImageFile.getThumbImage();
        try {
            //生成缩略图片
            thumbImageStream = generateThumbImageStream(inputStream, thumbImage);
            // 获取文件大小
            long fileSize = thumbImageStream.available();
            // 获取配置缩略图前缀
            String prefixName = thumbImage.getPrefixName();
            LOGGER.error("获取到缩略图前缀{}", prefixName);
            StorageUploadSlaveFileCommand command = new StorageUploadSlaveFileCommand(thumbImageStream, fileSize,
                    masterFilename, prefixName, fastImageFile.getFileExtName());
            connectionManager.executeFdfsCmd(client.getInetSocketAddress(), command);

        } catch (IOException e) {
            LOGGER.error("upload ThumbImage error", e);
            throw new FdfsUploadImageException("upload ThumbImage error", e.getCause());
        } finally {
            IOUtils.closeQuietly(thumbImageStream);
        }
    }
927697
@Override
    public boolean checkMgtKeyInUse(String CorpNum, MgtKeyType KeyType,
                                    String MgtKey) throws PopbillException {

        if (KeyType == null)
            throw new PopbillException(-99999999, "관리번호형태가 입력되지 않았습니다.");
        if (MgtKey == null || MgtKey.isEmpty())
            throw new PopbillException(-99999999, "관리번호가 입력되지 않았습니다.");

        try {
            TaxinvoiceInfo info = httpget("/Taxinvoice/" + KeyType.name() + "/"
                    + MgtKey, CorpNum, null, TaxinvoiceInfo.class);

            return (info.getItemKey() == null || info.getItemKey().isEmpty()) == false;
        } catch (PopbillException PE) {
            if (PE.getCode() == -11000005)
                return false;
            throw PE;
        }
    }
233578
function(socket, expectedCommand, expectedBodyLength, callback, headerOnly) {
        var oriCallback = callback
        // 收包完毕则关闭掉连接
        callback = function() {
            cleanup()
            if (is.function(oriCallback)) {
                oriCallback.apply(null, arguments)
            }
        }
        var headerBufferLen = protocol.HEADER_BYTE_LENGTH
        var headerBuffer = new Buffer(headerBufferLen)
        // 已填充的length
        var headerBufferFilled = 0
        // 解析后的header信息
        // {status: , bodyLength: }
        var header
        var bodyBuffer
        // 下1次要copy到bodyBuffer中的起始位置
        var bodyBufferStart = 0

        socket.on('data', listener)

        function listener(data) {
            // --------------- 收到服务器发来消息
            // -------- 解析header
            if (!header) {
                // header parsed
                if (headerBufferFilled + data.length >= headerBufferLen) {
                    var len = headerBufferFilled + data.length
                    // 只copy剩下的header部分
                    data.copy(headerBuffer, headerBufferFilled, 0, headerBufferLen - headerBufferFilled)
                    try {
                        header = _parseHeader(headerBuffer, expectedCommand, expectedBodyLength)
                        logger.debug('receive server packet header: %j', header)
                        // 无body时直接返回
                        if (header.bodyLength === 0) {
                            callback(null, header)
                            return
                        }

                        if (headerOnly) {
                            oriCallback(null, header)
                            if (len > headerBufferLen) {
                                oriCallback(null, data.slice(headerBufferLen - headerBufferFilled))
                            }
                            return
                        }

                        bodyBuffer = new Buffer(header.bodyLength)

                        // 还有body的数据则填充到body buffer中
                        if (len > headerBufferLen) {
                            data.copy(bodyBuffer, 0, headerBufferLen - headerBufferFilled)
                            bodyBufferStart = len - headerBufferLen
                            // 读取完毕
                            if (bodyBufferStart >= header.bodyLength) {
                                callback(null, bodyBuffer)
                            }
                        }

                    } catch (err) {
                        callback(err)
                    }

                } else {
                    data.copy(headerBuffer, headerBufferFilled)
                    headerBufferFilled += data.length
                }

            } else {
                // 交由外部处理
                if (headerOnly) {
                    oriCallback(null, data)
                    return
                }
                // ---------- 解析body
                data.copy(bodyBuffer, bodyBufferStart)
                bodyBufferStart += data.length
                // 读取完毕
                if (bodyBufferStart >= header.bodyLength) {
                    callback(null, bodyBuffer)
                }
            }
        }

        function cleanup() {
            socket.removeListener('data', listener)
            // 关闭连接
            protocol.closeSocket(socket)
        }
    }
55688
protected SofaResponse doSendMsg(ProviderInfo providerInfo, ClientTransport transport,
                                     SofaRequest request) throws SofaRpcException {
        RpcInternalContext context = RpcInternalContext.getContext();
        // 添加调用的服务端远程地址
        RpcInternalContext.getContext().setRemoteAddress(providerInfo.getHost(), providerInfo.getPort());
        try {
            checkProviderVersion(providerInfo, request); // 根据服务端版本特殊处理
            String invokeType = request.getInvokeType();
            int timeout = resolveTimeout(request, consumerConfig, providerInfo);

            SofaResponse response = null;
            // 同步调用
            if (RpcConstants.INVOKER_TYPE_SYNC.equals(invokeType)) {
                long start = RpcRuntimeContext.now();
                try {
                    response = transport.syncSend(request, timeout);
                } finally {
                    if (RpcInternalContext.isAttachmentEnable()) {
                        long elapsed = RpcRuntimeContext.now() - start;
                        context.setAttachment(RpcConstants.INTERNAL_KEY_CLIENT_ELAPSE, elapsed);
                    }
                }
            }
            // 单向调用
            else if (RpcConstants.INVOKER_TYPE_ONEWAY.equals(invokeType)) {
                long start = RpcRuntimeContext.now();
                try {
                    transport.oneWaySend(request, timeout);
                    response = buildEmptyResponse(request);
                } finally {
                    if (RpcInternalContext.isAttachmentEnable()) {
                        long elapsed = RpcRuntimeContext.now() - start;
                        context.setAttachment(RpcConstants.INTERNAL_KEY_CLIENT_ELAPSE, elapsed);
                    }
                }
            }
            // Callback调用
            else if (RpcConstants.INVOKER_TYPE_CALLBACK.equals(invokeType)) {
                // 调用级别回调监听器
                SofaResponseCallback sofaResponseCallback = request.getSofaResponseCallback();
                if (sofaResponseCallback == null) {
                    SofaResponseCallback methodResponseCallback = consumerConfig
                        .getMethodOnreturn(request.getMethodName());
                    if (methodResponseCallback != null) { // 方法的Callback
                        request.setSofaResponseCallback(methodResponseCallback);
                    }
                }
                // 记录发送开始时间
                context.setAttachment(RpcConstants.INTERNAL_KEY_CLIENT_SEND_TIME, RpcRuntimeContext.now());
                // 开始调用
                transport.asyncSend(request, timeout);
                response = buildEmptyResponse(request);
            }
            // Future调用
            else if (RpcConstants.INVOKER_TYPE_FUTURE.equals(invokeType)) {
                // 记录发送开始时间
                context.setAttachment(RpcConstants.INTERNAL_KEY_CLIENT_SEND_TIME, RpcRuntimeContext.now());
                // 开始调用
                ResponseFuture future = transport.asyncSend(request, timeout);
                // 放入线程上下文
                RpcInternalContext.getContext().setFuture(future);
                response = buildEmptyResponse(request);
            } else {
                throw new SofaRpcException(RpcErrorType.CLIENT_UNDECLARED_ERROR, "Unknown invoke type:" + invokeType);
            }
            return response;
        } catch (SofaRpcException e) {
            throw e;
        } catch (Throwable e) { // 客户端其它异常
            throw new SofaRpcException(RpcErrorType.CLIENT_UNDECLARED_ERROR, e);
        }
    }
1015731
private void disposeObtainedResult(SignInResult result, int rstCode) {
        if(result.isSuccess()){
            //可以获取帐号的 openid，昵称，头像 at信息
            SignInHuaweiId account = result.getSignInHuaweiId();
            onSignInResult(rstCode, account);
        } else {
            if(rstCode == HuaweiIdStatusCodes.SIGN_IN_UNLOGIN
                    || rstCode == HuaweiIdStatusCodes.SIGN_IN_AUTH
                    || rstCode == HuaweiIdStatusCodes.SIGN_IN_CHECK_PASSWORD){
                Activity curActivity = ActivityMgr.INST.getLastActivity();
                if (curActivity == null) {
                    HMSAgentLog.e("activity is null");
                    onSignInResult(HMSAgent.AgentResultCode.NO_ACTIVITY_FOR_USE, null);
                    return;
                }

                try {
                    signInResultForDispose = result;
                    Intent nxtIntent = new Intent(curActivity, HMSSignInAgentActivity.class);
                    curActivity.startActivity(nxtIntent);
                } catch (Exception e) {
                    HMSAgentLog.e("start HMSSignInAgentActivity error:" + e.getMessage());
                    onSignInResult(HMSAgent.AgentResultCode.START_ACTIVITY_ERROR, null);
                }
            } else {
                onSignInResult(rstCode, null);
            }
        }
    }
351743
@Override
    public void onConnect(int rst, HuaweiApiClient client) {

        HMSAgentLog.d("onConnect:" + rst);

        if (client == null || !ApiClientMgr.INST.isConnect(client)) {
            HMSAgentLog.e("client not connted");
            onPMSPayEnd(rst, null);
            return;
        }

        // 调用HMS-SDK pay 接口
        PendingResult<PayResult> payResult = HuaweiPay.HuaweiPayApi.productPay(client, payReq);
        payResult.setResultCallback(new ResultCallback<PayResult>() {
            @Override
            public void onResult(PayResult result) {

                if (result == null) {
                    HMSAgentLog.e("result is null");
                    onPMSPayEnd(HMSAgent.AgentResultCode.RESULT_IS_NULL, null);
                    return;
                }

                Status status = result.getStatus();
                if (status == null) {
                    HMSAgentLog.e("status is null");
                    onPMSPayEnd(HMSAgent.AgentResultCode.STATUS_IS_NULL, null);
                    return;
                }

                int rstCode = status.getStatusCode();
                HMSAgentLog.d("status=" + status);
                // 需要重试的错误码，并且可以重试
                if ((rstCode == CommonCode.ErrorCode.SESSION_INVALID
                        || rstCode == CommonCode.ErrorCode.CLIENT_API_INVALID) && retryTimes > 0) {
                    retryTimes--;
                    connect();
                } else if (rstCode == PayStatusCodes.PAY_STATE_SUCCESS) {
                    // 支付校验完成，取当前activity进行后续支付操作
                    Activity curActivity = ActivityMgr.INST.getLastActivity();
                    if (curActivity == null) {
                        HMSAgentLog.e("activity is null");
                        onPMSPayEnd(HMSAgent.AgentResultCode.NO_ACTIVITY_FOR_USE, null);
                        return;
                    }

                    if (statusForPay != null) {
                        HMSAgentLog.e("has already a pay to dispose");
                        onPMSPayEnd(HMSAgent.AgentResultCode.REQUEST_REPEATED, null);
                        return;
                    }

                    //启动支付流程
                    try {
                        statusForPay = status;
                        Intent intent = new Intent(curActivity, HMSPMSPayAgentActivity.class);
                        intent.putExtra(BaseAgentActivity.EXTRA_IS_FULLSCREEN, UIUtils.isActivityFullscreen(curActivity));
                        curActivity.startActivity(intent);
                    } catch (Exception e) {
                        HMSAgentLog.e("start HMSPayAgentActivity error:" + e.getMessage());
                        onPMSPayEnd(HMSAgent.AgentResultCode.START_ACTIVITY_ERROR, null);
                    }
                }else {
                    onPMSPayEnd(rstCode, null);
                }
            }
        });
    }
995128
private Authentication getAuthentication(SecurityContext securityContext) {
		// 用户未登录
		Authentication authentication = securityContext.getAuthentication();
		if (authentication == null) {
			authentication = new AnonymousAuthenticationToken(UUID.randomUUID().toString(), "anonymous",
					Collections.<GrantedAuthority> singletonList(new SimpleGrantedAuthority("ROLE_ANONYMOUS")));
		}
		return authentication;
	}
1130969
function getEtag(buffer,callback){

    // 判断传入的参数是buffer还是stream还是filepath
    var mode = 'buffer';

    if(typeof buffer === 'string'){
        buffer = require('fs').createReadStream(buffer);
        mode='stream';
    }else if(buffer instanceof require('stream')){
        mode='stream';
    }

    // sha1算法
    var sha1 = function(content){
        var crypto = require('crypto');
        var sha1 = crypto.createHash('sha1');
        sha1.update(content);
        return sha1.digest();
    };

    // 以4M为单位分割
    var blockSize = 4*1024*1024;
    var sha1String = [];
    var prefix = 0x16;
    var blockCount = 0;

    switch(mode){
        case 'buffer':
            var bufferSize = buffer.length;
            blockCount = Math.ceil(bufferSize / blockSize);

            for(var i=0;i<blockCount;i++){
                sha1String.push(sha1(buffer.slice(i*blockSize,(i+1)*blockSize)));
            }
            process.nextTick(function(){
                callback(calcEtag());
            });
            break;
        case 'stream':
            var stream = buffer;
            stream.on('readable', function() {
                var chunk;
                while (chunk = stream.read(blockSize)) {
                    sha1String.push(sha1(chunk));
                    blockCount++;
                }
            });
            stream.on('end',function(){
                callback(calcEtag());
            });
            break;
    }

    function calcEtag(){
        if(!sha1String.length){
            return 'Fto5o-5ea0sNMlW_75VgGJCv2AcJ';
        }
        var sha1Buffer = Buffer.concat(sha1String,blockCount * 20);

        // 如果大于4M，则对各个块的sha1结果再次sha1
        if(blockCount > 1){
            prefix = 0x96;
            sha1Buffer = sha1(sha1Buffer);
        }

        sha1Buffer = Buffer.concat(
            [new Buffer([prefix]),sha1Buffer],
            sha1Buffer.length + 1
        );

        return sha1Buffer.toString('base64')
            .replace(/\//g,'_').replace(/\+/g,'-');

    }

}
710653
@Override
	public Object call(Object[] args, Context context) {
		// 只能有一个参数且只能为字符串
		if ((args.length >= 1) && (args[0] instanceof String) && (args[0] != null)) {
			String spel = (String) args[0];
			Expression expression = getExpression(spel);
			// 如果有第二参数，取他作为根对象
			if ((args.length >= 2) && (args[1] != null)) {
				return expression.getValue(createEvaluationContext(args[1], context));
			} else {
				return expression.getValue(createEvaluationContext(Collections.emptyMap(), context));
			}
		}
		return null;
	}
664642
private int resolveTimeout(SofaRequest request, ConsumerConfig consumerConfig, ProviderInfo providerInfo) {
        // 先去调用级别配置
        Integer timeout = request.getTimeout();
        if (timeout == null) {
            // 取客户端配置（先方法级别再接口级别）
            timeout = consumerConfig.getMethodTimeout(request.getMethodName());
            if (timeout == null || timeout < 0) {
                // 再取服务端配置
                timeout = (Integer) providerInfo.getDynamicAttr(ATTR_TIMEOUT);
                if (timeout == null) {
                    // 取框架默认值
                    timeout = getIntValue(CONSUMER_INVOKE_TIMEOUT);
                }
            }
        }
        return timeout;
    }
879647
private static PublicKey getPublicKey(String modulus, String exponent) {
		try {
			BigInteger b1 = new BigInteger(modulus);
			BigInteger b2 = new BigInteger(exponent);
			KeyFactory keyFactory = KeyFactory.getInstance("RSA", "BC");
			RSAPublicKeySpec keySpec = new RSAPublicKeySpec(b1, b2);
			return keyFactory.generatePublic(keySpec);
		} catch (Exception e) {
			LogUtil.writeErrorLog("构造RSA公钥失败：" + e);
			return null;
		}
	}
344522
@Override
    public void onConnect(int rst, HuaweiApiClient client) {
        if (client == null || !ApiClientMgr.INST.isConnect(client)) {
            HMSAgentLog.e("client not connted");
            onSnsGetMsgIntentResult(rst, null);
            return;
        }

        PendingResult<IntentResult> sendMsgResult = HuaweiSns.HuaweiSnsApi.getMsgSendIntent(client, msg, needResult);
        sendMsgResult.setResultCallback(new ResultCallback<IntentResult>() {
            @Override
            public void onResult(IntentResult result) {
                if (result == null) {
                    HMSAgentLog.e("result is null");
                    onSnsGetMsgIntentResult(HMSAgent.AgentResultCode.RESULT_IS_NULL, null);
                    return;
                }

                Status status = result.getStatus();
                if (status == null) {
                    HMSAgentLog.e("status is null");
                    onSnsGetMsgIntentResult(HMSAgent.AgentResultCode.STATUS_IS_NULL, null);
                    return;
                }

                int rstCode = status.getStatusCode();
                HMSAgentLog.d("status=" + status);
                // 需要重试的错误码，并且可以重试
                if ((rstCode == CommonCode.ErrorCode.SESSION_INVALID
                        || rstCode == CommonCode.ErrorCode.CLIENT_API_INVALID) && retryTimes > 0) {
                    retryTimes--;
                    connect();
                } else if (rstCode == SNSCode.OK) {
                    //回调GetMsgIntent结果
                    Intent nxtIntent = result.getIntent();
                    if (nxtIntent == null) {
                        HMSAgentLog.e("nxtIntent is null");
                        onSnsGetMsgIntentResult(HMSAgent.AgentResultCode.RESULT_IS_NULL, null);
                        return;
                    } else {
                        onSnsGetMsgIntentResult(rstCode, nxtIntent);
                        return;
                    }

                }else {
                    onSnsGetMsgIntentResult(rstCode, null);
                }
            }
        });
    }
1152671
public HttpResponse execute(boolean isAsync) {
		// 初始化URL
		urlWithParamIfGet();
		// 编码URL
		if (this.encodeUrlParams) {
			this.url = HttpUtil.encodeParams(this.url, this.charset);
		}
		// 初始化 connection
		initConnecton();

		// 发送请求
		send();

		// 手动实现重定向
		HttpResponse httpResponse = sendRedirectIfPosible();

		// 获取响应
		if (null == httpResponse) {
			httpResponse = new HttpResponse(this.httpConnection, this.charset, isAsync, isIgnoreResponseBody());
		}
		return httpResponse;
	}
355081
function (string, userConfig) {
        // 空文件会导致错误
        if (string.trim() === '') {
            return '';
        }

        userConfig = userConfig || {};

        overwriteConfig(_config, userConfig); // overwrite codeStyle with user config

        // deal with indent (new Array(indent + 1)).join(' ')
        var INDENT = (function () {
            var indentStr = '';
            var space = _config.useTabIndent ? '\t' : ' ';
            var indent = _config.indent ? Number(_config.indent) : 4;
            while (indent--) {
                indentStr += space;
            }
            return indentStr;
        })();

        /**
         * create a LineBreak token
         *
         * @returns {{type: string, value: string, formatter: boolean}}
         */
        var nextLineFactory = function () {
            return {
                type: 'LineBreak',
                value: _config.lineSeparator,
                formatter: true
            };
        };

        /**
         * create a indent token with indent level
         *
         * @returns {Object}
         */
        var indentFactory = function () {
            var indentStr = '';
            for (var i = 0; i < indentLevel; i++) {
                indentStr += INDENT;
            }
            return {
                type: 'WhiteSpace',
                value: indentStr
            };
        };

        /**
         * create a indent token with only one indent
         *
         * @returns {Object}
         */
        var singleIndentFactory = function () {
            return {
                type: 'WhiteSpace',
                value: INDENT
            };
        };

        /**
         * create a single space token
         *
         * @returns {Object}
         */
        var whiteSpaceFactory = function () {
            return {
                type: 'WhiteSpace',
                value: ' '
            };
        };

        /**
         * check if a token is comment
         *
         * @param {Object} token - the token to check
         * @returns {boolean}
         */
        var isComment = function (token) {
            return token.type === 'LineComment' || token.type === 'BlockComment';
        };

        /**
         * check if a token is comment LineComment
         *
         * @param {Object} token - the token to check
         * @returns {boolean}
         */
        var isLineComment = function (token) {
            return token.type === 'LineComment';
        };

        /**
         * check if a token is comment BlockComment
         *
         * @param {Object} token - the token to check
         * @returns {boolean}
         */
        var isBlockComment = function (token) {
            return token.type === 'BlockComment';
        };

        /**
         * check if a token is white space
         *
         * @param {Object} token - the token to check
         * @returns {boolean}
         */
        var isWhiteSpace = function (token) {
            return token.type === 'WhiteSpace';
        };

        /**
         * check if a token is line break
         *
         * @param {Object} token - the token to check
         * @returns {boolean}
         */
        var isLineBreak = function (token) {
            return token.type === 'LineBreak';
        };

        /**
         * check if a token is comment in one line
         *
         * @param {Object} token - the token to check
         * @returns {boolean}
         */
        var isInlineComment = function (token) {
            var inline = false;
            if (token) {
                if (token.type === 'LineComment') {
                    inline = true;
                } else if (token.type === 'BlockComment') {
                    inline = (token.value.indexOf('\n') === -1);
                }
            }
            return inline;
        };

        /**
         * check if only types between startToken and endToken
         *
         * @param {Object} startToken - the token to start check
         * @param {Object} endToken - the token to end check
         * @param {Array} types - allow types array
         * @returns {boolean}
         */
        var isTypeBetween = function (startToken, endToken, types) {
            var is = true;
            var token = startToken;
            while (token.next && token.next !== endToken) {
                token = token.next;
                if (types.indexOf(token.type) === -1) {
                    is = false;
                    break;
                }
            }
            return is;
        };

        /**
         * 保证一个语句节点是在新起一行
         *
         * @param {Object} node - target node
         */
        var guaranteeNewLine = function (node) {
            if (node.startToken.prev && node.startToken.prev.type !== 'LineBreak') {
                insertBefore(node.startToken, nextLineFactory());
            }
        };

        /**
         * 保证一个token两侧是空白符
         *
         * @param {Object} token - target token
         */
        var guaranteeWhiteSpaceAround = function (token) {
            if (token.prev.type !== 'WhiteSpace') {
                insertBefore(token, whiteSpaceFactory());
            }
            if (token.next.type !== 'WhiteSpace' && token.next.type !== 'LineBreak') {
                insertAfter(token, whiteSpaceFactory());
            }
        };

        /**
         * insert token before a token
         *
         * @param {Object} token - target token
         * @param {Object} insertion - a token to insert
         */
        var insertBefore = function (token, insertion) {
            if (!token.prev) { // insert at first
                token.prev = insertion;
                insertion.next = token;
            } else {
                token.prev.next = insertion;
                insertion.prev = token.prev;
                insertion.next = token;
                token.prev = insertion;
            }
        };

        /**
         * insert token after a token
         *
         * @param {Object} token - target token
         * @param {Object} insertion - a token to insert
         */
        var insertAfter = function (token, insertion) {
            if (!token.next) { // insert at last
                token.next = insertion;
                insertion.prev = token;
            } else {
                token.next.prev = insertion;
                insertion.next = token.next;
                insertion.prev = token;
                token.next = insertion;
            }
        };

        /**
         * remove token in tokens
         *
         * @param {Object} token - target token
         */
        var removeToken = function (token) {
            if (token.prev && token.next) {
                token.prev.next = token.next;
                token.next.prev = token.prev;
            } else if (token.prev) {
                token.prev.next = undefined;
            } else if (token.next) {
                token.next.prev = undefined;
            }
        };

        /**
         * 这堆操作符前后是要有空白的
         *
         * @type {string[]}
         */
        var SPACE_AROUND_PUNCTUATOR = [
            '=', '+=', '-=', '*=', '/=', '%=', '<<=', '>>=', '>>>=', '&=', '^=', '|=',
            '==', '!=', '===', '!==', '>', '>=', '<', '<=',
            '+', '-', '*', '/', '%',
            '&', '|', '^', '~', '<<', '>>', '>>>',
            '&&', '||'
        ];

        var _rocambole = require('rocambole');

        // 先fix再format
        string = require('./lib/fix').fix(string, _config.fix);

        try {
            var _ast = _rocambole.parse(string);
        } catch (e) {
            return string;
        }

        // start clear
        // 先去除空白
        var clearWhiteSpace = function (token) {
            if (isWhiteSpace(token)) {
                // 默认都要删除空白
                var remove = true;

                // 空白前面是换行 && 后面是注释的不删除
                if (token.prev && token.next && isLineBreak(token.prev) && isComment(token.next)) {
                    remove = false;
                }

                if (remove) {
                    removeToken(token);
                }
            }

            if (isLineComment(token)) {
                token.raw = token.raw.trimRight();
            }

            if (isBlockComment(token)) {
                var rawArray = token.raw.split(_config.lineSeparator);
                rawArray.forEach(function (line, i) {
                    rawArray[i] = line.trimRight();
                });
                token.raw = rawArray.join(_config.lineSeparator);
            }
        };
        var token = _ast.startToken;
        while (token !== _ast.endToken.next) {
            clearWhiteSpace(token);
            token = token.next;
        }

        if (_config.blankLines.keepMaxBlankLines > 0) {
            _rocambole.recursive(_ast, function (node) {
                var keep = 0;
                var t;
                if (/Declaration|Statement/.test(node.type) && node.type !== 'BlockStatement' && !(node.type === 'VariableDeclaration' && node.parent.type === 'ForStatement')) {
                    keep = Number(_config.blankLines.keepMaxBlankLines);
                    if (node.endToken.next && isLineBreak(node.endToken.next)) {
                        t = node.endToken.next;
                        t.removeAble = false;
                        while (keep--) {
                            if (t.next && isLineBreak(t.next)) {
                                t.next.removeAble = false;
                                t = t.next;
                            }
                        }
                    }
                }
                if (node.type === 'Property') {
                    keep = Number(_config.blankLines.keepMaxBlankLines);
                    if (node.startToken.prev && isLineBreak(node.startToken.prev)) {
                        t = node.startToken.prev;
                        t.removeAble = false;
                        while (keep--) {
                            if (t.prev && isLineBreak(t.prev)) {
                                t.prev.removeAble = false;
                                t = t.prev;
                            }
                        }
                    }
                }
            });
        }
        var clearLineBreak = function (token) {
            // 注释前后的换行一律保留，其他一律删除
            if (isLineBreak(token)) {
                // 默认都要删除换行
                var remove = true;

                // 注释前面的
                if (token.next && isComment(token.next)) {
                    remove = false;
                }
                // 注释后面的
                if (token.prev && isComment(token.prev)) {
                    remove = false;
                }
                // 注释前面空白再前面的，这种是有缩进且占整行的注释
                if (token.next && token.next.next && isWhiteSpace(token.next) && isComment(token.next.next)) {
                    remove = false;
                }

                if (token.prev && !token.prev.prev && Number(_config.blankLines.keepMaxBlankLines) > 0 && isComment(token.prev) && token.prev.value.charAt(0) === '*') {
                    if (token.next && isLineBreak(token.next)) {
                        token.next.removeAble = false;
                        token.next.next.removeAble = false;
                    }
                }
                if (token.removeAble === false) {
                    remove = false;
                }

                if (remove) {
                    removeToken(token);
                }
            }
        };
        token = _ast.startToken;
        while (token !== _ast.endToken.next) {
            clearLineBreak(token);
            token = token.next;
        }
        // end clear

        // start process
        // 这些关键词之后，必须无脑保证空白，其实return,delete等并不是必须要空白，但是应该没有傻逼这么写吧return(a);忽略这种情况
        // 如果这些关键词后面都不加空白，那就傻逼鉴定完毕 shit 所以不提供这种配置
        var INSERT_SPACE_AFTER_KEYWORD = ['throw', 'return', 'delete', 'new', 'in', 'typeof', 'instanceof', 'case', 'void'];
        // 这几个关键词属于同一类型，在它们后边可以加空白也可以不加，都不会出先语法错误
        var INSERT_SPACE_AFTER_KEYWORD_WITH_CONFIG = ['if', 'for', 'while', 'switch', 'catch'];
        var processToken = function (token) {
            // 必须加空白的地方
            if (token.type === 'Keyword' && INSERT_SPACE_AFTER_KEYWORD.indexOf(token.value) !== -1) {
                insertAfter(token, whiteSpaceFactory());
            }
            // 坑：var后面可以是换行，这时候就不需要空白
            if (
                token.type === 'Keyword'
                && (token.value === 'var' || token.value === 'let' || token.value === 'const')
                && !isLineBreak(token.next)
            ) {
                insertAfter(token, whiteSpaceFactory());
            }

            if (_config.spaces.before.parentheses && token.type === 'Keyword' && INSERT_SPACE_AFTER_KEYWORD_WITH_CONFIG.indexOf(token.value) !== -1) {
                insertAfter(token, whiteSpaceFactory());
            }

            // check around = WhiteSpace
            if (_config.spaces.around.binaryOperators && token.type === 'Punctuator' && SPACE_AROUND_PUNCTUATOR.indexOf(token.value) !== -1) {
                guaranteeWhiteSpaceAround(token);
            }
            // 特殊处理in/instanceof，这货两边必须保证空白
            if (token.type === 'Keyword' && ['in', 'instanceof'].indexOf(token.value) !== -1) {
                guaranteeWhiteSpaceAround(token);
            }

            // 特殊处理finally，这货在ast里不是一个独立type节点
            if (token.type === 'Keyword' && token.value === 'finally') {
                if (_config.spaces.before.keywords && !isWhiteSpace(token.prev)) {
                    insertBefore(token, whiteSpaceFactory());
                }
            }
        };
        token = _ast.startToken;
        while (token !== _ast.endToken.next) {
            processToken(token);
            token = token.next;
        }
        // end process

        // loop node
        _rocambole.recursive(_ast, function (node) {
            switch (node.type) {
                case 'ArrayExpression':
                    node.startToken.indentIncrease = true;
                    node.endToken.indentDecrease = true;
                    node.elements.forEach(function (el) {
                        el && guaranteeNewLine(el);
                    });
                    if (node.elements.length > 0 && !isLineBreak(node.endToken.prev)) {
                        insertBefore(node.endToken, nextLineFactory());
                    }
                    break;
                case 'BreakStatement':
                    guaranteeNewLine(node);
                    break;
                case 'ConditionalExpression':
                    if (_config.spaces.around.ternaryOperators && node.test) {
                        (function () {
                            var token = node.test.endToken;
                            // TODO 这样做到底安全不？
                            while (!(token.value === '?' && token.type === 'Punctuator')) {
                                token = token.next;
                            }
                            if (!isWhiteSpace(token.prev)) {
                                insertBefore(token, whiteSpaceFactory());
                            }
                            if (!isWhiteSpace(token.next)) {
                                insertAfter(token, whiteSpaceFactory());
                            }
                        })();
                    }
                    if (_config.spaces.around.ternaryOperators && node.consequent) {
                        (function () {
                            var token = node.consequent.endToken;
                            while (!(token.value === ':' && token.type === 'Punctuator')) {
                                token = token.next;
                            }
                            if (!isWhiteSpace(token.prev)) {
                                insertBefore(token, whiteSpaceFactory());
                            }
                            if (!isWhiteSpace(token.next)) {
                                insertAfter(token, whiteSpaceFactory());
                            }
                        })();
                    }
                    break;
                case 'ContinueStatement':
                    guaranteeNewLine(node);
                    break;
                case 'DoWhileStatement':
                    guaranteeNewLine(node);
                    if (node.body.type === 'BlockStatement') {
                        if (!isWhiteSpace(node.body.endToken.next)) {
                            _config.spaces.before.keywords && insertAfter(node.body.endToken, whiteSpaceFactory());
                        }
                    } else {
                        if (isWhiteSpace(node.startToken.next)) {
                            removeToken(node.startToken.next);
                        }
                        node.body.startToken.indentSelf = true;
                        if (!isWhiteSpace(node.test.startToken.prev.prev)) {
                            if (!isLineBreak(node.test.startToken.prev.prev.prev)) {
                                insertBefore(node.test.startToken.prev.prev, nextLineFactory());
                            }
                            insertBefore(node.test.startToken.prev, whiteSpaceFactory());
                        } else {
                            if (!isLineBreak(node.test.startToken.prev.prev.prev.prev)) {
                                insertBefore(node.test.startToken.prev.prev.prev, nextLineFactory());
                            }
                        }
                    }
                    break;
                case 'ForStatement':
                    guaranteeNewLine(node);
                    if (node.test && !isWhiteSpace(node.test.startToken.prev)) {
                        insertBefore(node.test.startToken, whiteSpaceFactory());
                    }
                    if (node.update && !isWhiteSpace(node.update.startToken.prev)) {
                        insertBefore(node.update.startToken, whiteSpaceFactory());
                    }
                    if (_config.spaces.within.parentheses) {
                        if (node.init && !isWhiteSpace(node.init.startToken.prev)) {
                            insertBefore(node.init.startToken, whiteSpaceFactory());
                        } else {}
                        if (node.update && !isWhiteSpace(node.update.endToken.next)) {
                            insertAfter(node.update.endToken, whiteSpaceFactory());
                        }
                    }
                    break;
                case 'ForInStatement':
                    guaranteeNewLine(node);
                    break;
                case 'VariableDeclaration':
                    if (node.parent.type !== 'ForStatement' && node.parent.type !== 'ForInStatement') {
                        guaranteeNewLine(node);
                    }
                    break;
                case 'VariableDeclarator':
                    if (node.endToken.next && node.endToken.next.type === 'Punctuator' && node.endToken.next.value === ',' && !isLineBreak(node.endToken.next.next)) {
                        insertAfter(node.endToken.next, whiteSpaceFactory());
                    }
                    break;
                case 'ExpressionStatement':
                    guaranteeNewLine(node);
                    break;
                case 'FunctionDeclaration':
                    guaranteeNewLine(node);
                    insertAfter(node.startToken, whiteSpaceFactory());
                    if (node.id) {
                        _config.spaces.before.functionDeclarationParentheses && insertAfter(node.id.endToken, whiteSpaceFactory());
                    }
                    node.params.forEach(function (param, i) {
                        if (i > 0) {
                            insertBefore(param.startToken, whiteSpaceFactory());
                        }
                    });
                    if (_config.spaces.within.parentheses && node.params.length > 0) {
                        if (!isWhiteSpace(node.params[0].startToken.prev)) {
                            insertBefore(node.params[0].startToken, whiteSpaceFactory());
                        }
                        if (!isWhiteSpace(node.params[node.params.length - 1].endToken.next)) {
                            insertAfter(node.params[node.params.length - 1].endToken, whiteSpaceFactory());
                        }
                    }
                    break;
                case 'IfStatement':
                    // 坑：if statement 的 consequent 和 alternate 都是有可能不存在的
                    if (node.parent.type !== 'IfStatement') {
                        guaranteeNewLine(node);
                    } else {
                        insertBefore(node.startToken, whiteSpaceFactory());
                    }
                    if (node.consequent && node.consequent.type !== 'BlockStatement') {
                        node.consequent.startToken.indentSelf = true;
                        if (node.alternate && node.consequent.endToken.next && !isLineBreak(node.consequent.endToken.next)) {
                            insertAfter(node.consequent.endToken, nextLineFactory());
                        }
                    } else {
                        if (node.alternate) {
                            _config.spaces.before.keywords && insertAfter(node.consequent.endToken, whiteSpaceFactory());
                        }
                    }
                    if (node.alternate && node.alternate.type !== 'BlockStatement' && node.alternate.type !== 'IfStatement') {
                        node.alternate.startToken.indentSelf = true;
                    }
                    if (_config.spaces.within.parentheses && node.test) {
                        if (!isWhiteSpace(node.test.startToken.prev)) {
                            insertBefore(node.test.startToken, whiteSpaceFactory());
                        }
                        if (!isWhiteSpace(node.test.endToken.next)) {
                            insertAfter(node.test.endToken, whiteSpaceFactory());
                        }
                    }
                    break;
                case 'ReturnStatement':
                    guaranteeNewLine(node);
                    break;
                case 'BlockStatement':
                    node.startToken.indentIncrease = true;
                    node.endToken.indentDecrease = true;
                    if (node.startToken.prev && !isWhiteSpace(node.startToken.prev) && !isLineBreak(node.startToken.prev)) {
                        _config.spaces.before.leftBrace && insertBefore(node.startToken, whiteSpaceFactory());
                    }
                    if (!isLineBreak(node.endToken.prev)) {
                        insertBefore(node.endToken, nextLineFactory());
                    }
                    break;
                case 'ObjectExpression':
                    if (!isTypeBetween(node.startToken, node.endToken, ['WhiteSpace', 'LineBreak'])) {
                        node.startToken.indentIncrease = true;
                        node.endToken.indentDecrease = true;
                        if (!isLineBreak(node.endToken.prev)) {
                            insertBefore(node.endToken, nextLineFactory());
                        }
                    }
                    break;
                case 'Property':
                    guaranteeNewLine(node);
                    if (_config.spaces.other.beforePropertyNameValueSeparator) {
                        !isWhiteSpace(node.key.endToken.next) && insertAfter(node.key.endToken, whiteSpaceFactory());
                    }
                    if (_config.spaces.other.afterPropertyNameValueSeparator) {
                        !isWhiteSpace(node.value.startToken.prev) && insertBefore(node.value.startToken, whiteSpaceFactory());
                    }
                    break;
                case 'CallExpression':
                    node.arguments.forEach(function (arg, i) {
                        if (i !== 0) {
                            insertBefore(arg.startToken, whiteSpaceFactory());
                        }
                    });
                    if (_config.spaces.within.parentheses && node.arguments.length > 0) {
                        if (!isWhiteSpace(node.arguments[0].startToken.prev)) {
                            insertBefore(node.arguments[0].startToken, whiteSpaceFactory());
                        }
                        if (!isWhiteSpace(node.arguments[node.arguments.length - 1].endToken.next)) {
                            insertAfter(node.arguments[node.arguments.length - 1].endToken, whiteSpaceFactory());
                        }
                    }
                    break;
                case 'FunctionExpression':
                    if (_config.spaces.before.functionExpressionParentheses || node.id) {
                        insertAfter(node.startToken, whiteSpaceFactory());
                    }
                    node.params.forEach(function (param, i, array) {
                        if (param.endToken.next && param.endToken.next.type === 'Punctuator' && param.endToken.next.value === ',') {
                            insertAfter(param.endToken.next, whiteSpaceFactory());
                        }
                    });
                    if (_config.spaces.within.parentheses && node.params.length > 0) {
                        if (!isWhiteSpace(node.params[0].startToken.prev)) {
                            insertBefore(node.params[0].startToken, whiteSpaceFactory());
                        }
                        if (!isWhiteSpace(node.params[node.params.length - 1].endToken.next)) {
                            insertAfter(node.params[node.params.length - 1].endToken, whiteSpaceFactory());
                        }
                    }
                    break;
                case 'SequenceExpression':
                    node.expressions.forEach(function (exp) {
                        if (exp.endToken.next && exp.endToken.next.type === 'Punctuator' && exp.endToken.next.value === ',') {
                            insertAfter(exp.endToken.next, whiteSpaceFactory());
                        }
                    });
                    break;
                case 'UnaryExpression':
                    if (['+', '-', '!'].indexOf(node.startToken.value) !== -1) {
                        if (node.startToken.next.type === 'WhiteSpace') {
                            removeToken(node.startToken.next);
                        }
                    }
                    if (node.operator === 'void') {
                        if (node.startToken.next.type !== 'WhiteSpace') {
                            insertAfter(node.startToken, whiteSpaceFactory());
                        }
                    }
                    break;
                case 'WhileStatement':
                    guaranteeNewLine(node);
                    if (_config.spaces.within.parentheses && node.test) {
                        if (!isWhiteSpace(node.test.startToken.prev)) {
                            insertBefore(node.test.startToken, whiteSpaceFactory());
                        }
                        if (!isWhiteSpace(node.test.endToken.next)) {
                            insertAfter(node.test.endToken, whiteSpaceFactory());
                        }
                    }
                    break;
                case 'SwitchStatement':
                    guaranteeNewLine(node);
                    node.discriminant.endToken.next.indentIncrease = true;
                    _config.spaces.before.leftBrace && insertAfter(node.discriminant.endToken.next, whiteSpaceFactory());
                    node.endToken.indentDecrease = true;
                    if (!isLineBreak(node.endToken.prev)) {
                        insertBefore(node.endToken, nextLineFactory());
                    }
                    if (_config.spaces.within.parentheses && node.discriminant) {
                        if (!isWhiteSpace(node.discriminant.startToken.prev)) {
                            insertBefore(node.discriminant.startToken, whiteSpaceFactory());
                        }
                        if (!isWhiteSpace(node.discriminant.endToken.next)) {
                            insertAfter(node.discriminant.endToken, whiteSpaceFactory());
                        }
                    }
                    break;
                case 'SwitchCase':
                    guaranteeNewLine(node);
                    node.startToken.indentIncrease = true;
                    node.endToken.indentDecrease = true;
                    break;
                case 'ThrowStatement':
                    guaranteeNewLine(node);
                    break;
                case 'TryStatement':
                    guaranteeNewLine(node);
                    break;
                case 'CatchClause':
                    if (_config.spaces.before.keywords && !isWhiteSpace(node.startToken.prev)) {
                        insertBefore(node.startToken, whiteSpaceFactory());
                    }
                    if (_config.spaces.within.parentheses && node.param) {
                        if (!isWhiteSpace(node.param.startToken.prev)) {
                            insertBefore(node.param.startToken, whiteSpaceFactory());
                        }
                        if (!isWhiteSpace(node.param.endToken.next)) {
                            insertAfter(node.param.endToken, whiteSpaceFactory());
                        }
                    }
                    break;
                case 'EmptyStatement':
                    guaranteeNewLine(node);
                    break;
                default:
                    break;
            }
        });

        // process indent start
        // 缩进这块要单独拿出来处理，不然很容易混乱
        var indentLevel = 0;
        var processIndent = function (token) {
            if (token.indentIncrease) {
                indentLevel++;
            }
            if (token.type === 'LineBreak') {
                if (token.next && !isWhiteSpace(token.next) && !isLineBreak(token.next)) {
                    // 如果下一个token是要减小缩进的，那它本身就是要减少缩进的
                    if (token.next.indentDecrease) {
                        indentLevel--;
                        token.next.indentDecrease = false;
                    }
                    insertAfter(token, indentFactory());
                }
            }
            if (token.indentDecrease) {
                indentLevel--;
            }
            if (token.indentSelf) {
                indentLevel++;
                insertBefore(token, singleIndentFactory());
                indentLevel--;
            }
        };
        token = _ast.startToken;
        while (token !== _ast.endToken.next) {
            processIndent(token);
            token = token.next;
        }
        // process indent end

        // 单独的处理注释的逻辑
        var processComment = function (token) {
            // 行尾注释保持跟前面的代码一个空格的距离
            if (isLineComment(token) && token.prev && !isWhiteSpace(token.prev)) {
                insertBefore(token, whiteSpaceFactory());
            }
        };
        token = _ast.startToken;
        while (token !== _ast.endToken.next) {
            processComment(token);
            token = token.next;
        }


        var formattedString = _ast.toString();
        if (_config.blankLines.atEndOfFile) {
            if (formattedString.charAt(formattedString.length - 1) !== _config.lineSeparator) {
                formattedString += _config.lineSeparator;
            }
        } else {
            formattedString = formattedString.trim();
        }
        return formattedString;
    }
697945
function checkInvokeReadyState() {
            var readyState = DEP_READY;

            // 先判断resource是否加载完成。如果resource未加载完成，则认为未准备好
            each(
                module.depRs,
                function ( dep ) {
                    if ( !( dep.absId && modIsDefined( dep.absId ) ) ) {
                        readyState = DEP_UNREADY;
                        return false;
                    }
                }
            );

            if ( readyState !== DEP_READY ) {
                return readyState;
            }

            // 检查所有依赖模块，根据以下因素处理readyState
            // 1. 是否定义完成
            // 2. 是否强依赖
            // 3. 是否循环依赖
            each(
                module.depMs,
                function ( dep ) {
                    if ( modIsDefined( dep.absId ) ) {
                        return;
                    }

                    // dep.circular相当于一层cache，尽量减少modHasCircularDependency多次调用的开销
                    if ( dep.circular === CIRCULAR_DEP_UNREADY ) {
                        dep.circular = modHasCircularDependency( id, dep.absId );
                    }

                    switch ( dep.circular ) {
                        case CIRCULAR_DEP_YES:
                            if ( dep.hard ) {
                                readyState = DEP_ANALYZED;
                            }
                            break;
                        case CIRCULAR_DEP_NO:
                            readyState = DEP_ANALYZED;
                            break;
                        case CIRCULAR_DEP_UNREADY:
                            readyState = DEP_UNREADY;
                            return false;
                    }
                }
            );

            return readyState;
        }