Input: TODO : Batching should be implemented at the renderer level not within the reconciler . [CODESPLIT] function flushSync ( fn , a ) { ! ! isRendering ? invariant ( false , 'flushSync was called from inside a lifecycle method. It cannot be called when React is already rendering.' ) : void 0 ; var previousIsBatchingUpdates = isBatchingUpdates ; isBatchingUpdates = true ; try { return syncUpdates ( fn , a ) ; } finally { isBatchingUpdates = previousIsBatchingUpdates ; performSyncWork ( ) ; } }


Input: This file intentionally does * not * have the Flow annotation . Don t add it . See . / inline - typed . js for an explanation . [CODESPLIT] function createPortal$1 ( children , containerInfo , // TODO: figure out the API for cross-renderer implementation. implementation ) { var key = arguments . length > 3 && arguments [ 3 ] !== undefined ? arguments [ 3 ] : null ; return { // This tag allow us to uniquely identify this as a React Portal $$typeof : REACT_PORTAL_TYPE , key : key == null ? null : '' + key , children : children , containerInfo : containerInfo , implementation : implementation } ; }


Input: / * eslint - disable no - use - before - define / * eslint - enable no - use - before - define [CODESPLIT] function ReactBatch ( root ) { var expirationTime = computeUniqueAsyncExpiration ( ) ; this . _expirationTime = expirationTime ; this . _root = root ; this . _next = null ; this . _callbacks = null ; this . _didComplete = false ; this . _hasChildren = false ; this . _children = null ; this . _defer = true ; }


Input: Base class helpers for the updating state of a component . [CODESPLIT] function Component ( props , context , updater ) { this . props = props ; this . context = context ; // If a component has string refs, we will assign a different object later. this . refs = emptyObject ; // We initialize the default updater but the real one gets injected by the // renderer. this . updater = updater || ReactNoopUpdateQueue ; }


Input: Flatten a children object ( typically specified as props . children ) and return an array with appropriately re - keyed children . [CODESPLIT] function toArray ( children ) { var result = [ ] ; mapIntoWithKeyPrefixInternal ( children , result , null , function ( child ) { return child ; } ) ; return result ; }


Input: Given an element validate that its props follow the propTypes definition provided by the type . [CODESPLIT] function validatePropTypes ( element ) { var type = element . type ; var name = void 0 , propTypes = void 0 ; if ( typeof type === 'function' ) { // Class or functional component name = type . displayName || type . name ; propTypes = type . propTypes ; } else if ( typeof type === 'object' && type !== null && type . $$typeof === REACT_FORWARD_REF_TYPE ) { // ForwardRef var functionName = type . render . displayName || type . render . name || '' ; name = type . displayName || ( functionName !== '' ? 'ForwardRef(' + functionName + ')' : 'ForwardRef' ) ; propTypes = type . propTypes ; } else { return ; } if ( propTypes ) { setCurrentlyValidatingElement ( element ) ; checkPropTypes ( propTypes , element . props , 'prop' , name , ReactDebugCurrentFrame . getStackAddendum ) ; setCurrentlyValidatingElement ( null ) ; } else if ( type . PropTypes !== undefined && ! propTypesMisspellWarningShown ) { propTypesMisspellWarningShown = true ; warningWithoutStack$1 ( false , 'Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?' , name || 'Unknown' ) ; } if ( typeof type . getDefaultProps === 'function' ) { ! type . getDefaultProps . isReactClassApproved ? warningWithoutStack$1 ( false , 'getDefaultProps is only used on classic React.createClass ' + 'definitions. Use a static property named `defaultProps` instead.' ) : void 0 ; } }


Input: Given a fragment validate that it can only be provided with fragment props [CODESPLIT] function validateFragmentProps ( fragment ) { setCurrentlyValidatingElement ( fragment ) ; var keys = Object . keys ( fragment . props ) ; for ( var i = 0 ; i < keys . length ; i ++ ) { var key = keys [ i ] ; if ( key !== 'children' && key !== 'key' ) { warning$1 ( false , 'Invalid prop `%s` supplied to `React.Fragment`. ' + 'React.Fragment can only have `key` and `children` props.' , key ) ; break ; } } if ( fragment . ref !== null ) { warning$1 ( false , 'Invalid attribute `ref` supplied to `React.Fragment`.' ) ; } setCurrentlyValidatingElement ( null ) ; }


Input: Bucket 相关 查看是否存在该Bucket，是否有权限访问 [CODESPLIT] function headBucket ( params , callback ) { submitRequest . call ( this , { Action : 'name/cos:HeadBucket' , Bucket : params . Bucket , Region : params . Region , headers : params . Headers , method : 'HEAD' , } , function ( err , data ) { callback ( err , data ) ; } ) ; }


Input: 获取 Bucket 下的 object 列表 [CODESPLIT] function getBucket ( params , callback ) { var reqParams = { } ; reqParams [ 'prefix' ] = params [ 'Prefix' ] || '' ; reqParams [ 'delimiter' ] = params [ 'Delimiter' ] ; reqParams [ 'marker' ] = params [ 'Marker' ] ; reqParams [ 'max-keys' ] = params [ 'MaxKeys' ] ; reqParams [ 'encoding-type' ] = params [ 'EncodingType' ] ; submitRequest . call ( this , { Action : 'name/cos:GetBucket' , ResourceKey : reqParams [ 'prefix' ] , method : 'GET' , Bucket : params . Bucket , Region : params . Region , headers : params . Headers , qs : reqParams , } , function ( err , data ) { if ( err ) { return callback ( err ) ; } var ListBucketResult = data . ListBucketResult || { } ; var Contents = ListBucketResult . Contents || [ ] ; var CommonPrefixes = ListBucketResult . CommonPrefixes || [ ] ; Contents = util . isArray ( Contents ) ? Contents : [ Contents ] ; CommonPrefixes = util . isArray ( CommonPrefixes ) ? CommonPrefixes : [ CommonPrefixes ] ; var result = util . clone ( ListBucketResult ) ; util . extend ( result , { Contents : Contents , CommonPrefixes : CommonPrefixes , statusCode : data . statusCode , headers : data . headers , } ) ; callback ( null , result ) ; } ) ; }


Input: 获取 Bucket 的 权限列表 [CODESPLIT] function getBucketAcl ( params , callback ) { submitRequest . call ( this , { Action : 'name/cos:GetBucketACL' , method : 'GET' , Bucket : params . Bucket , Region : params . Region , headers : params . Headers , action : 'acl' , } , function ( err , data ) { if ( err ) { return callback ( err ) ; } var AccessControlPolicy = data . AccessControlPolicy || { } ; var Owner = AccessControlPolicy . Owner || { } ; var Grant = AccessControlPolicy . AccessControlList . Grant || [ ] ; Grant = util . isArray ( Grant ) ? Grant : [ Grant ] ; var result = decodeAcl ( AccessControlPolicy ) ; if ( data . headers && data . headers [ 'x-cos-acl' ] ) { result . ACL = data . headers [ 'x-cos-acl' ] ; } result = util . extend ( result , { Owner : Owner , Grants : Grant , statusCode : data . statusCode , headers : data . headers , } ) ; callback ( null , result ) ; } ) ; }


Input: 获取 Bucket 的 跨域设置 [CODESPLIT] function getBucketCors ( params , callback ) { submitRequest . call ( this , { Action : 'name/cos:GetBucketCORS' , method : 'GET' , Bucket : params . Bucket , Region : params . Region , headers : params . Headers , action : 'cors' , } , function ( err , data ) { if ( err ) { if ( err . statusCode === 404 && err . error && err . error . Code === 'NoSuchCORSConfiguration' ) { var result = { CORSRules : [ ] , statusCode : err . statusCode , } ; err . headers && ( result . headers = err . headers ) ; callback ( null , result ) ; } else { callback ( err ) ; } return ; } var CORSConfiguration = data . CORSConfiguration || { } ; var CORSRules = CORSConfiguration . CORSRules || CORSConfiguration . CORSRule || [ ] ; CORSRules = util . clone ( util . isArray ( CORSRules ) ? CORSRules : [ CORSRules ] ) ; util . each ( CORSRules , function ( rule ) { util . each ( [ 'AllowedOrigin' , 'AllowedHeader' , 'AllowedMethod' , 'ExposeHeader' ] , function ( key , j ) { var sKey = key + 's' ; var val = rule [ sKey ] || rule [ key ] || [ ] ; delete rule [ key ] ; rule [ sKey ] = util . isArray ( val ) ? val : [ val ] ; } ) ; } ) ; callback ( null , { CORSRules : CORSRules , statusCode : data . statusCode , headers : data . headers , } ) ; } ) ; }


Input: 设置 Bucket 的 跨域设置 [CODESPLIT] function putBucketCors ( params , callback ) { var CORSConfiguration = params [ 'CORSConfiguration' ] || { } ; var CORSRules = CORSConfiguration [ 'CORSRules' ] || params [ 'CORSRules' ] || [ ] ; CORSRules = util . clone ( util . isArray ( CORSRules ) ? CORSRules : [ CORSRules ] ) ; util . each ( CORSRules , function ( rule ) { util . each ( [ 'AllowedOrigin' , 'AllowedHeader' , 'AllowedMethod' , 'ExposeHeader' ] , function ( key , k ) { var sKey = key + 's' ; var val = rule [ sKey ] || rule [ key ] || [ ] ; delete rule [ sKey ] ; rule [ key ] = util . isArray ( val ) ? val : [ val ] ; } ) ; } ) ; var xml = util . json2xml ( { CORSConfiguration : { CORSRule : CORSRules } } ) ; var headers = params . Headers ; headers [ 'Content-Type' ] = 'application/xml' ; headers [ 'Content-MD5' ] = util . binaryBase64 ( util . md5 ( xml ) ) ; submitRequest . call ( this , { Action : 'name/cos:PutBucketCORS' , method : 'PUT' , Bucket : params . Bucket , Region : params . Region , body : xml , action : 'cors' , headers : headers , } , function ( err , data ) { if ( err ) { return callback ( err ) ; } callback ( null , { statusCode : data . statusCode , headers : data . headers , } ) ; } ) ; }


Input: 删除 Bucket 的 跨域设置 [CODESPLIT] function deleteBucketCors ( params , callback ) { submitRequest . call ( this , { Action : 'name/cos:DeleteBucketCORS' , method : 'DELETE' , Bucket : params . Bucket , Region : params . Region , headers : params . Headers , action : 'cors' , } , function ( err , data ) { if ( err && err . statusCode === 204 ) { return callback ( null , { statusCode : err . statusCode } ) ; } else if ( err ) { return callback ( err ) ; } callback ( null , { statusCode : data . statusCode || err . statusCode , headers : data . headers , } ) ; } ) ; }


Input: 获取 Bucket 的 地域信息 [CODESPLIT] function getBucketLocation ( params , callback ) { submitRequest . call ( this , { Action : 'name/cos:GetBucketLocation' , method : 'GET' , Bucket : params . Bucket , Region : params . Region , headers : params . Headers , action : 'location' , } , function ( err , data ) { if ( err ) { return callback ( err ) ; } callback ( null , data ) ; } ) ; }


Input: 获取 Bucket 的读取权限策略 [CODESPLIT] function getBucketPolicy ( params , callback ) { submitRequest . call ( this , { Action : 'name/cos:GetBucketPolicy' , method : 'GET' , Bucket : params . Bucket , Region : params . Region , headers : params . Headers , action : 'policy' , rawBody : true , } , function ( err , data ) { if ( err ) { if ( err . statusCode && err . statusCode === 403 ) { return callback ( { ErrorStatus : 'Access Denied' } ) ; } if ( err . statusCode && err . statusCode === 405 ) { return callback ( { ErrorStatus : 'Method Not Allowed' } ) ; } if ( err . statusCode && err . statusCode === 404 ) { return callback ( { ErrorStatus : 'Policy Not Found' } ) ; } return callback ( err ) ; } var Policy = { } ; try { Policy = JSON . parse ( data . body ) ; } catch ( e ) { } callback ( null , { Policy : Policy , statusCode : data . statusCode , headers : data . headers , } ) ; } ) ; }


Input: 获取 Bucket 的标签设置 [CODESPLIT] function getBucketTagging ( params , callback ) { submitRequest . call ( this , { Action : 'name/cos:GetBucketTagging' , method : 'GET' , Bucket : params . Bucket , Region : params . Region , headers : params . Headers , action : 'tagging' , } , function ( err , data ) { if ( err ) { if ( err . statusCode === 404 && err . error && ( err . error === "Not Found" || err . error . Code === 'NoSuchTagSet' ) ) { var result = { Tags : [ ] , statusCode : err . statusCode , } ; err . headers && ( result . headers = err . headers ) ; callback ( null , result ) ; } else { callback ( err ) ; } return ; } var Tags = [ ] ; try { Tags = data . Tagging . TagSet . Tag || [ ] ; } catch ( e ) { } Tags = util . clone ( util . isArray ( Tags ) ? Tags : [ Tags ] ) ; callback ( null , { Tags : Tags , statusCode : data . statusCode , headers : data . headers , } ) ; } ) ; }


Input: 设置 Bucket 的标签 [CODESPLIT] function putBucketTagging ( params , callback ) { var Tagging = params [ 'Tagging' ] || { } ; var Tags = Tagging . TagSet || Tagging . Tags || params [ 'Tags' ] || [ ] ; Tags = util . clone ( util . isArray ( Tags ) ? Tags : [ Tags ] ) ; var xml = util . json2xml ( { Tagging : { TagSet : { Tag : Tags } } } ) ; var headers = params . Headers ; headers [ 'Content-Type' ] = 'application/xml' ; headers [ 'Content-MD5' ] = util . binaryBase64 ( util . md5 ( xml ) ) ; submitRequest . call ( this , { Action : 'name/cos:PutBucketTagging' , method : 'PUT' , Bucket : params . Bucket , Region : params . Region , body : xml , action : 'tagging' , headers : headers , } , function ( err , data ) { if ( err && err . statusCode === 204 ) { return callback ( null , { statusCode : err . statusCode } ) ; } else if ( err ) { return callback ( err ) ; } callback ( null , { statusCode : data . statusCode , headers : data . headers , } ) ; } ) ; }


Input: Object 相关 取回对应Object的元数据，Head的权限与Get的权限一致 [CODESPLIT] function headObject ( params , callback ) { submitRequest . call ( this , { Action : 'name/cos:HeadObject' , method : 'HEAD' , Bucket : params . Bucket , Region : params . Region , Key : params . Key , VersionId : params . VersionId , headers : params . Headers , } , function ( err , data ) { if ( err ) { var statusCode = err . statusCode ; if ( params . Headers [ 'If-Modified-Since' ] && statusCode && statusCode === 304 ) { return callback ( null , { NotModified : true , statusCode : statusCode , } ) ; } return callback ( err ) ; } if ( data . headers && data . headers . etag ) { data . ETag = data . headers && data . headers . etag ; } callback ( null , data ) ; } ) ; }


Input: 下载 object [CODESPLIT] function getObject ( params , callback ) { var reqParams = { } ; reqParams [ 'response-content-type' ] = params [ 'ResponseContentType' ] ; reqParams [ 'response-content-language' ] = params [ 'ResponseContentLanguage' ] ; reqParams [ 'response-expires' ] = params [ 'ResponseExpires' ] ; reqParams [ 'response-cache-control' ] = params [ 'ResponseCacheControl' ] ; reqParams [ 'response-content-disposition' ] = params [ 'ResponseContentDisposition' ] ; reqParams [ 'response-content-encoding' ] = params [ 'ResponseContentEncoding' ] ; // 如果用户自己传入了 output submitRequest . call ( this , { Action : 'name/cos:GetObject' , method : 'GET' , Bucket : params . Bucket , Region : params . Region , Key : params . Key , VersionId : params . VersionId , headers : params . Headers , qs : reqParams , rawBody : true , } , function ( err , data ) { if ( err ) { var statusCode = err . statusCode ; if ( params . Headers [ 'If-Modified-Since' ] && statusCode && statusCode === 304 ) { return callback ( null , { NotModified : true } ) ; } return callback ( err ) ; } var result = { } ; result . Body = data . body ; if ( data . headers && data . headers . etag ) { result . ETag = data . headers && data . headers . etag ; } util . extend ( result , { statusCode : data . statusCode , headers : data . headers , } ) ; callback ( null , result ) ; } ) ; }


Input: 上传 object [CODESPLIT] function putObject ( params , callback ) { var self = this ; var FileSize = params . ContentLength ; var onProgress = util . throttleOnProgress . call ( self , FileSize , params . onProgress ) ; // 特殊处理 Cache-Control var headers = params . Headers ; ! headers [ 'Cache-Control' ] && ( headers [ 'Cache-Control' ] = '' ) ; // 获取 File 或 Blob 的 type 属性，如果有，作为文件 Content-Type var ContentType = headers [ 'Content-Type' ] || ( params . Body && params . Body . type ) ; ! headers [ 'Content-Type' ] && ContentType && ( headers [ 'Content-Type' ] = ContentType ) ; util . getBodyMd5 ( self . options . UploadCheckContentMd5 , params . Body , function ( md5 ) { md5 && ( params . Headers [ 'Content-MD5' ] = util . binaryBase64 ( md5 ) ) ; if ( params . ContentLength !== undefined ) { params . Headers [ 'Content-Length' ] = params . ContentLength ; } submitRequest . call ( self , { Action : 'name/cos:PutObject' , TaskId : params . TaskId , method : 'PUT' , Bucket : params . Bucket , Region : params . Region , Key : params . Key , headers : params . Headers , body : params . Body , onProgress : onProgress , } , function ( err , data ) { if ( err ) { onProgress ( null , true ) ; return callback ( err ) ; } onProgress ( { loaded : FileSize , total : FileSize } , true ) ; if ( data && data . headers && data . headers [ 'etag' ] ) { var url = getUrl ( { ForcePathStyle : self . options . ForcePathStyle , protocol : self . options . Protocol , domain : self . options . Domain , bucket : params . Bucket , region : params . Region , object : params . Key , } ) ; url = url . substr ( url . indexOf ( '://' ) + 3 ) ; return callback ( null , { Location : url , ETag : data . headers [ 'etag' ] , statusCode : data . statusCode , headers : data . headers , } ) ; } callback ( null , data ) ; } ) ; } ) ; }


Input: 删除 object [CODESPLIT] function deleteObject ( params , callback ) { submitRequest . call ( this , { Action : 'name/cos:DeleteObject' , method : 'DELETE' , Bucket : params . Bucket , Region : params . Region , Key : params . Key , headers : params . Headers , VersionId : params . VersionId , } , function ( err , data ) { if ( err ) { var statusCode = err . statusCode ; if ( statusCode && statusCode === 204 ) { return callback ( null , { statusCode : statusCode } ) ; } else if ( statusCode && statusCode === 404 ) { return callback ( null , { BucketNotFound : true , statusCode : statusCode , } ) ; } else { return callback ( err ) ; } } callback ( null , { statusCode : data . statusCode , headers : data . headers , } ) ; } ) ; }


Input: 设置 object 的 权限列表 [CODESPLIT] function putObjectAcl ( params , callback ) { var headers = params . Headers ; var xml = '' ; if ( params [ 'AccessControlPolicy' ] ) { var AccessControlPolicy = util . clone ( params [ 'AccessControlPolicy' ] || { } ) ; var Grants = AccessControlPolicy . Grants || AccessControlPolicy . Grant ; Grants = util . isArray ( Grants ) ? Grants : [ Grants ] ; delete AccessControlPolicy . Grant ; delete AccessControlPolicy . Grants ; AccessControlPolicy . AccessControlList = { Grant : Grants } ; xml = util . json2xml ( { AccessControlPolicy : AccessControlPolicy } ) ; headers [ 'Content-Type' ] = 'application/xml' ; headers [ 'Content-MD5' ] = util . binaryBase64 ( util . md5 ( xml ) ) ; } // Grant Header 去重 util . each ( headers , function ( val , key ) { if ( key . indexOf ( 'x-cos-grant-' ) === 0 ) { headers [ key ] = uniqGrant ( headers [ key ] ) ; } } ) ; submitRequest . call ( this , { Action : 'name/cos:PutObjectACL' , method : 'PUT' , Bucket : params . Bucket , Region : params . Region , Key : params . Key , action : 'acl' , headers : headers , body : xml , } , function ( err , data ) { if ( err ) { return callback ( err ) ; } callback ( null , { statusCode : data . statusCode , headers : data . headers , } ) ; } ) ; }


Input: Options Object请求实现跨域访问的预请求。即发出一个 OPTIONS 请求给服务器以确认是否可以进行跨域操作。 [CODESPLIT] function optionsObject ( params , callback ) { var headers = params . Headers ; headers [ 'Origin' ] = params [ 'Origin' ] ; headers [ 'Access-Control-Request-Method' ] = params [ 'AccessControlRequestMethod' ] ; headers [ 'Access-Control-Request-Headers' ] = params [ 'AccessControlRequestHeaders' ] ; submitRequest . call ( this , { Action : 'name/cos:OptionsObject' , method : 'OPTIONS' , Bucket : params . Bucket , Region : params . Region , Key : params . Key , headers : headers , } , function ( err , data ) { if ( err ) { if ( err . statusCode && err . statusCode === 403 ) { return callback ( null , { OptionsForbidden : true , statusCode : err . statusCode } ) ; } return callback ( err ) ; } var headers = data . headers || { } ; callback ( null , { AccessControlAllowOrigin : headers [ 'access-control-allow-origin' ] , AccessControlAllowMethods : headers [ 'access-control-allow-methods' ] , AccessControlAllowHeaders : headers [ 'access-control-allow-headers' ] , AccessControlExposeHeaders : headers [ 'access-control-expose-headers' ] , AccessControlMaxAge : headers [ 'access-control-max-age' ] , statusCode : data . statusCode , headers : data . headers , } ) ; } ) ; }


Input: 分块上传 初始化分块上传 [CODESPLIT] function multipartInit ( params , callback ) { var xml ; var headers = params . Headers ; var userAgent = navigator && navigator . userAgent || '' ; var m = userAgent . match ( /  TBS\/(\d{6})  / ) ; if ( location . protocol === 'http:' && m && m [ 1 ] . length <= 6 && m [ 1 ] < '044429' ) { xml = util . json2xml ( { } ) ; headers [ 'Content-MD5' ] = util . binaryBase64 ( util . md5 ( xml ) ) ; // 如果没有 Content-Type 指定一个 if ( ! headers [ 'Content-Type' ] ) { headers [ 'Content-Type' ] = ( params . Body && params . Body . type ) || 'application/octet-stream' ; } } // 特殊处理 Cache-Control ! headers [ 'Cache-Control' ] && ( headers [ 'Cache-Control' ] = '' ) ; submitRequest . call ( this , { Action : 'name/cos:InitiateMultipartUpload' , method : 'POST' , Bucket : params . Bucket , Region : params . Region , Key : params . Key , action : 'uploads' , headers : params . Headers , body : xml , } , function ( err , data ) { if ( err ) { return callback ( err ) ; } data = util . clone ( data || { } ) ; if ( data && data . InitiateMultipartUploadResult ) { return callback ( null , util . extend ( data . InitiateMultipartUploadResult , { statusCode : data . statusCode , headers : data . headers , } ) ) ; } callback ( null , data ) ; } ) ; }


Input: 完成分块上传 [CODESPLIT] function multipartComplete ( params , callback ) { var self = this ; var UploadId = params . UploadId ; var Parts = params [ 'Parts' ] ; for ( var i = 0 , len = Parts . length ; i < len ; i ++ ) { if ( Parts [ i ] [ 'ETag' ] . indexOf ( '"' ) === 0 ) { continue ; } Parts [ i ] [ 'ETag' ] = '"' + Parts [ i ] [ 'ETag' ] + '"' ; } var xml = util . json2xml ( { CompleteMultipartUpload : { Part : Parts } } ) ; var headers = params . Headers ; headers [ 'Content-Type' ] = 'application/xml' ; headers [ 'Content-MD5' ] = util . binaryBase64 ( util . md5 ( xml ) ) ; submitRequest . call ( this , { Action : 'name/cos:CompleteMultipartUpload' , method : 'POST' , Bucket : params . Bucket , Region : params . Region , Key : params . Key , qs : { uploadId : UploadId } , body : xml , headers : headers , } , function ( err , data ) { if ( err ) { return callback ( err ) ; } var url = getUrl ( { ForcePathStyle : self . options . ForcePathStyle , protocol : self . options . Protocol , domain : self . options . Domain , bucket : params . Bucket , region : params . Region , object : params . Key , isLocation : true , } ) ; var CompleteMultipartUploadResult = data . CompleteMultipartUploadResult || { } ; var result = util . extend ( CompleteMultipartUploadResult , { Location : url , statusCode : data . statusCode , headers : data . headers , } ) ; callback ( null , result ) ; } ) ; }


Input: 分块上传任务列表查询 [CODESPLIT] function multipartList ( params , callback ) { var reqParams = { } ; reqParams [ 'delimiter' ] = params [ 'Delimiter' ] ; reqParams [ 'encoding-type' ] = params [ 'EncodingType' ] ; reqParams [ 'prefix' ] = params [ 'Prefix' ] || '' ; reqParams [ 'max-uploads' ] = params [ 'MaxUploads' ] ; reqParams [ 'key-marker' ] = params [ 'KeyMarker' ] ; reqParams [ 'upload-id-marker' ] = params [ 'UploadIdMarker' ] ; reqParams = util . clearKey ( reqParams ) ; submitRequest . call ( this , { Action : 'name/cos:ListMultipartUploads' , ResourceKey : reqParams [ 'prefix' ] , method : 'GET' , Bucket : params . Bucket , Region : params . Region , headers : params . Headers , qs : reqParams , action : 'uploads' , } , function ( err , data ) { if ( err ) { return callback ( err ) ; } if ( data && data . ListMultipartUploadsResult ) { var Upload = data . ListMultipartUploadsResult . Upload || [ ] ; var CommonPrefixes = data . ListMultipartUploadsResult . CommonPrefixes || [ ] ; CommonPrefixes = util . isArray ( CommonPrefixes ) ? CommonPrefixes : [ CommonPrefixes ] ; Upload = util . isArray ( Upload ) ? Upload : [ Upload ] ; data . ListMultipartUploadsResult . Upload = Upload ; data . ListMultipartUploadsResult . CommonPrefixes = CommonPrefixes ; } var result = util . clone ( data . ListMultipartUploadsResult || { } ) ; util . extend ( result , { statusCode : data . statusCode , headers : data . headers , } ) ; callback ( null , result ) ; } ) ; }


Input: 上传的分块列表查询 [CODESPLIT] function multipartListPart ( params , callback ) { var reqParams = { } ; reqParams [ 'uploadId' ] = params [ 'UploadId' ] ; reqParams [ 'encoding-type' ] = params [ 'EncodingType' ] ; reqParams [ 'max-parts' ] = params [ 'MaxParts' ] ; reqParams [ 'part-number-marker' ] = params [ 'PartNumberMarker' ] ; submitRequest . call ( this , { Action : 'name/cos:ListParts' , method : 'GET' , Bucket : params . Bucket , Region : params . Region , Key : params . Key , headers : params . Headers , qs : reqParams , } , function ( err , data ) { if ( err ) { return callback ( err ) ; } var ListPartsResult = data . ListPartsResult || { } ; var Part = ListPartsResult . Part || [ ] ; Part = util . isArray ( Part ) ? Part : [ Part ] ; ListPartsResult . Part = Part ; var result = util . clone ( ListPartsResult ) ; util . extend ( result , { statusCode : data . statusCode , headers : data . headers , } ) ; callback ( null , result ) ; } ) ; }


Input: 抛弃分块上传 [CODESPLIT] function multipartAbort ( params , callback ) { var reqParams = { } ; reqParams [ 'uploadId' ] = params [ 'UploadId' ] ; submitRequest . call ( this , { Action : 'name/cos:AbortMultipartUpload' , method : 'DELETE' , Bucket : params . Bucket , Region : params . Region , Key : params . Key , headers : params . Headers , qs : reqParams , } , function ( err , data ) { if ( err ) { return callback ( err ) ; } callback ( null , { statusCode : data . statusCode , headers : data . headers , } ) ; } ) ; }


Input: 获取签名 [CODESPLIT] function getAuth ( params ) { var self = this ; return util . getAuth ( { SecretId : params . SecretId || this . options . SecretId || '' , SecretKey : params . SecretKey || this . options . SecretKey || '' , Method : params . Method , Key : params . Key , Query : params . Query , Headers : params . Headers , Expires : params . Expires , UseRawKey : self . options . UseRawKey , SystemClockOffset : self . options . SystemClockOffset , } ) ; }


Input: 获取文件下载链接 [CODESPLIT] function getObjectUrl ( params , callback ) { var self = this ; var url = getUrl ( { ForcePathStyle : self . options . ForcePathStyle , protocol : params . Protocol || self . options . Protocol , domain : self . options . Domain , bucket : params . Bucket , region : params . Region , object : params . Key , } ) ; if ( params . Sign !== undefined && ! params . Sign ) { callback ( null , { Url : url } ) ; return url ; } var AuthData = getAuthorizationAsync . call ( this , { Action : ( ( params . Method || '' ) . toUpperCase ( ) === 'PUT' ? 'name/cos:PutObject' : 'name/cos:GetObject' ) , Bucket : params . Bucket || '' , Region : params . Region || '' , Method : params . Method || 'get' , Key : params . Key , Expires : params . Expires , } , function ( err , AuthData ) { if ( ! callback ) return ; if ( err ) { callback ( err ) ; return ; } var signUrl = url ; signUrl += '?' + ( AuthData . Authorization . indexOf ( 'q-signature' ) > - 1 ? AuthData . Authorization : 'sign=' + encodeURIComponent ( AuthData . Authorization ) ) ; AuthData . XCosSecurityToken && ( signUrl += '&x-cos-security-token=' + AuthData . XCosSecurityToken ) ; AuthData . ClientIP && ( signUrl += '&clientIP=' + AuthData . ClientIP ) ; AuthData . ClientUA && ( signUrl += '&clientUA=' + AuthData . ClientUA ) ; AuthData . Token && ( signUrl += '&token=' + AuthData . Token ) ; setTimeout ( function ( ) { callback ( null , { Url : signUrl } ) ; } ) ; } ) ; if ( AuthData ) { return url + '?' + AuthData . Authorization + ( AuthData . XCosSecurityToken ? '&x-cos-security-token=' + AuthData . XCosSecurityToken : '' ) ; } else { return url ; } }


Input: 私有方法 [CODESPLIT] function decodeAcl ( AccessControlPolicy ) { var result = { GrantFullControl : [ ] , GrantWrite : [ ] , GrantRead : [ ] , GrantReadAcp : [ ] , GrantWriteAcp : [ ] , ACL : '' , } ; var GrantMap = { 'FULL_CONTROL' : 'GrantFullControl' , 'WRITE' : 'GrantWrite' , 'READ' : 'GrantRead' , 'READ_ACP' : 'GrantReadAcp' , 'WRITE_ACP' : 'GrantWriteAcp' , } ; var Grant = AccessControlPolicy . AccessControlList . Grant ; if ( Grant ) { Grant = util . isArray ( Grant ) ? Grant : [ Grant ] ; } var PublicAcl = { READ : 0 , WRITE : 0 , FULL_CONTROL : 0 } ; Grant . length && util . each ( Grant , function ( item ) { if ( item . Grantee . ID === 'qcs::cam::anyone:anyone' || item . Grantee . URI === 'http://cam.qcloud.com/groups/global/AllUsers' ) { PublicAcl [ item . Permission ] = 1 ; } else if ( item . Grantee . ID !== AccessControlPolicy . Owner . ID ) { result [ GrantMap [ item . Permission ] ] . push ( 'id="' + item . Grantee . ID + '"' ) ; } } ) ; if ( PublicAcl . FULL_CONTROL || ( PublicAcl . WRITE && PublicAcl . READ ) ) { result . ACL = 'public-read-write' ; } else if ( PublicAcl . READ ) { result . ACL = 'public-read' ; } else { result . ACL = 'private' ; } util . each ( GrantMap , function ( item ) { result [ item ] = uniqGrant ( result [ item ] . join ( ',' ) ) ; } ) ; return result ; }


Input: Grant 去重 [CODESPLIT] function uniqGrant ( str ) { var arr = str . split ( ',' ) ; var exist = { } ; var i , item ; for ( i = 0 ; i < arr . length ; ) { item = arr [ i ] . trim ( ) ; if ( exist [ item ] ) { arr . splice ( i , 1 ) ; } else { exist [ item ] = true ; arr [ i ] = item ; i ++ ; } } return arr . join ( ',' ) ; }


Input: 生成操作 url [CODESPLIT] function getUrl ( params ) { var longBucket = params . bucket ; var shortBucket = longBucket . substr ( 0 , longBucket . lastIndexOf ( '-' ) ) ; var appId = longBucket . substr ( longBucket . lastIndexOf ( '-' ) + 1 ) ; var domain = params . domain ; var region = params . region ; var object = params . object ; var protocol = params . protocol || ( util . isBrowser && location . protocol === 'http:' ? 'http:' : 'https:' ) ; if ( ! domain ) { if ( [ 'cn-south' , 'cn-south-2' , 'cn-north' , 'cn-east' , 'cn-southwest' , 'sg' ] . indexOf ( region ) > - 1 ) { domain = '{Region}.myqcloud.com' ; } else { domain = 'cos.{Region}.myqcloud.com' ; } if ( ! params . ForcePathStyle ) { domain = '{Bucket}.' + domain ; } } domain = domain . replace ( / \{\{AppId\}\} / ig , appId ) . replace ( / \{\{Bucket\}\} / ig , shortBucket ) . replace ( / \{\{Region\}\} / ig , region ) . replace ( / \{\{.*?\}\} / ig , '' ) ; domain = domain . replace ( / \{AppId\} / ig , appId ) . replace ( / \{BucketName\} / ig , shortBucket ) . replace ( / \{Bucket\} / ig , longBucket ) . replace ( / \{Region\} / ig , region ) . replace ( / \{.*?\} / ig , '' ) ; if ( ! / ^[a-zA-Z]+:\/\/ / . test ( domain ) ) { domain = protocol + '//' + domain ; } // 去掉域名最后的斜杆 if ( domain . slice ( - 1 ) === '/' ) { domain = domain . slice ( 0 , - 1 ) ; } var url = domain ; if ( params . ForcePathStyle ) { url += '/' + longBucket ; } url += '/' ; if ( object ) { url += util . camSafeUrlEncode ( object ) . replace ( / %2F / g , '/' ) ; } if ( params . isLocation ) { url = url . replace ( / ^https?:\/\/ / , '' ) ; } return url ; }


Input: 获取签名并发起请求 [CODESPLIT] function submitRequest ( params , callback ) { var self = this ; // 处理 headers ! params . headers && ( params . headers = { } ) ; // 处理 query ! params . qs && ( params . qs = { } ) ; params . VersionId && ( params . qs . versionId = params . VersionId ) ; params . qs = util . clearKey ( params . qs ) ; // 清理 undefined 和 null 字段 params . headers && ( params . headers = util . clearKey ( params . headers ) ) ; params . qs && ( params . qs = util . clearKey ( params . qs ) ) ; var Query = util . clone ( params . qs ) ; params . action && ( Query [ params . action ] = '' ) ; var next = function ( tryIndex ) { var oldClockOffset = self . options . SystemClockOffset ; getAuthorizationAsync . call ( self , { Bucket : params . Bucket || '' , Region : params . Region || '' , Method : params . method , Key : params . Key , Query : Query , Headers : params . headers , Action : params . Action , ResourceKey : params . ResourceKey , Scope : params . Scope , } , function ( err , AuthData ) { params . AuthData = AuthData ; _submitRequest . call ( self , params , function ( err , data ) { if ( err && tryIndex < 2 && ( oldClockOffset !== self . options . SystemClockOffset || allowRetry . call ( self , err ) ) ) { if ( params . headers ) { delete params . headers . Authorization ; delete params . headers [ 'token' ] ; delete params . headers [ 'clientIP' ] ; delete params . headers [ 'clientUA' ] ; delete params . headers [ 'x-cos-security-token' ] ; } next ( tryIndex + 1 ) ; } else { callback ( err , data ) ; } } ) ; } ) ; } ; next ( 0 ) ; }


Input: 发起请求 [CODESPLIT] function _submitRequest ( params , callback ) { var self = this ; var TaskId = params . TaskId ; if ( TaskId && ! self . _isRunningTask ( TaskId ) ) return ; var bucket = params . Bucket ; var region = params . Region ; var object = params . Key ; var method = params . method || 'GET' ; var url = params . url ; var body = params . body ; var json = params . json ; var rawBody = params . rawBody ; // url url = url || getUrl ( { ForcePathStyle : self . options . ForcePathStyle , protocol : self . options . Protocol , domain : self . options . Domain , bucket : bucket , region : region , object : object , } ) ; if ( params . action ) { url = url + '?' + params . action ; } var opt = { method : method , url : url , headers : params . headers , qs : params . qs , body : body , json : json , } ; // 获取签名 opt . headers . Authorization = params . AuthData . Authorization ; params . AuthData . Token && ( opt . headers [ 'token' ] = params . AuthData . Token ) ; params . AuthData . ClientIP && ( opt . headers [ 'clientIP' ] = params . AuthData . ClientIP ) ; params . AuthData . ClientUA && ( opt . headers [ 'clientUA' ] = params . AuthData . ClientUA ) ; params . AuthData . XCosSecurityToken && ( opt . headers [ 'x-cos-security-token' ] = params . AuthData . XCosSecurityToken ) ; // 清理 undefined 和 null 字段 opt . headers && ( opt . headers = util . clearKey ( opt . headers ) ) ; opt = util . clearKey ( opt ) ; // progress if ( params . onProgress && typeof params . onProgress === 'function' ) { var contentLength = body && ( body . size || body . length ) || 0 ; opt . onProgress = function ( e ) { if ( TaskId && ! self . _isRunningTask ( TaskId ) ) return ; var loaded = e ? e . loaded : 0 ; params . onProgress ( { loaded : loaded , total : contentLength } ) ; } ; } if ( this . options . Timeout ) { opt . timeout = this . options . Timeout ; } self . emit ( 'before-send' , opt ) ; var sender = REQUEST ( opt , function ( err , response , body ) { if ( err === 'abort' ) return ; // 返回内容添加 状态码 和 headers var hasReturned ; var cb = function ( err , data ) { TaskId && self . off ( 'inner-kill-task' , killTask ) ; if ( hasReturned ) return ; hasReturned = true ; var attrs = { } ; response && response . statusCode && ( attrs . statusCode = response . statusCode ) ; response && response . headers && ( attrs . headers = response . headers ) ; if ( err ) { err = util . extend ( err || { } , attrs ) ; callback ( err , null ) ; } else { data = util . extend ( data || { } , attrs ) ; callback ( null , data ) ; } sender = null ; } ; // 请求错误，发生网络错误 if ( err ) { cb ( { error : err } ) ; return ; } var jsonRes ; try { jsonRes = body && body . indexOf ( '<' ) > - 1 && body . indexOf ( '>' ) > - 1 && util . xml2json ( body ) || { } ; } catch ( e ) { jsonRes = body || { } ; } // 请求返回码不为 200 var statusCode = response . statusCode ; var statusSuccess = Math . floor ( statusCode / 100 ) === 2 ; // 200 202 204 206 if ( ! statusSuccess ) { cb ( { error : jsonRes . Error || jsonRes } ) ; return ; } // 不对 body 进行转换，body 直接挂载返回 if ( rawBody ) { jsonRes = { } ; jsonRes . body = body ; } if ( jsonRes . Error ) { cb ( { error : jsonRes . Error } ) ; return ; } cb ( null , jsonRes ) ; } ) ; // kill task var killTask = function ( data ) { if ( data . TaskId === TaskId ) { sender && sender . abort && sender . abort ( ) ; self . off ( 'inner-kill-task' , killTask ) ; } } ; TaskId && self . on ( 'inner-kill-task' , killTask ) ; }


Input: kill task [CODESPLIT] function ( data ) { if ( data . TaskId === TaskId ) { sender && sender . abort && sender . abort ( ) ; self . off ( 'inner-kill-task' , killTask ) ; } }


Input: v4 签名 [CODESPLIT] function ( opt ) { var pathname = opt . Pathname || '/' ; var expires = opt . Expires ; var ShortBucketName = '' ; var AppId = '' ; var match = opt . Bucket . match ( / ^(.+)-(\d+)$ / ) ; if ( match ) { ShortBucketName = match [ 1 ] ; AppId = match [ 2 ] ; } var random = parseInt ( Math . random ( ) * Math . pow ( 2 , 32 ) ) ; var now = parseInt ( Date . now ( ) / 1000 ) ; var e = now + ( expires === undefined ? 900 : ( expires * 1 || 0 ) ) ; // 默认签名过期时间为当前时间 + 900s var path = '/' + AppId + '/' + ShortBucketName + encodeURIComponent ( pathname ) . replace ( / %2F / g , '/' ) ; //多次签名这里填空 var plainText = 'a=' + AppId + '&b=' + ShortBucketName + '&k=' + opt . SecretId + '&e=' + e + '&t=' + now + '&r=' + random + '&f=' + path ; var sha1Res = CryptoJS . HmacSHA1 ( plainText , opt . SecretKey ) ; var strWordArray = CryptoJS . enc . Utf8 . parse ( plainText ) ; var resWordArray = sha1Res . concat ( strWordArray ) ; var sign = resWordArray . toString ( CryptoJS . enc . Base64 ) ; return sign ; }


Input: v5 签名 [CODESPLIT] function ( opt ) { if ( ! opt . SecretId ) return console . error ( 'missing param SecretId' ) ; if ( ! opt . SecretKey ) return console . error ( 'missing param SecretKey' ) ; if ( opt . Version === '4.0' ) { return CosAuthV4 ( opt ) ; } opt = opt || { } ; var SecretId = opt . SecretId ; var SecretKey = opt . SecretKey ; var method = ( opt . Method || 'get' ) . toLowerCase ( ) ; var query = opt . Query || { } ; var headers = opt . Headers || { } ; var pathname = opt . Pathname || '/' ; var expires = opt . Expires ; var getObjectKeys = function ( obj ) { var list = [ ] ; for ( var key in obj ) { if ( obj . hasOwnProperty ( key ) ) { list . push ( key ) ; } } return list . sort ( function ( a , b ) { a = a . toLowerCase ( ) ; b = b . toLowerCase ( ) ; return a === b ? 0 : ( a > b ? 1 : - 1 ) ; } ) ; } ; var obj2str = function ( obj ) { var i , key , val ; var list = [ ] ; var keyList = getObjectKeys ( obj ) ; for ( i = 0 ; i < keyList . length ; i ++ ) { key = keyList [ i ] ; val = ( obj [ key ] === undefined || obj [ key ] === null ) ? '' : ( '' + obj [ key ] ) ; key = key . toLowerCase ( ) ; key = camSafeUrlEncode ( key ) ; val = camSafeUrlEncode ( val ) || '' ; list . push ( key + '=' + val ) } return list . join ( '&' ) ; } ; // 签名有效起止时间 var now = parseInt ( new Date ( ) . getTime ( ) / 1000 ) - 1 ; var exp = now + ( expires === undefined ? 900 : ( expires * 1 || 0 ) ) ; // 默认签名过期时间为当前时间 + 900s // 要用到的 Authorization 参数列表 var qSignAlgorithm = 'sha1' ; var qAk = SecretId ; var qSignTime = now + ';' + exp ; var qKeyTime = now + ';' + exp ; var qHeaderList = getObjectKeys ( headers ) . join ( ';' ) . toLowerCase ( ) ; var qUrlParamList = getObjectKeys ( query ) . join ( ';' ) . toLowerCase ( ) ; // 签名算法说明文档：https://www.qcloud.com/document/product/436/7778 // 步骤一：计算 SignKey var signKey = CryptoJS . HmacSHA1 ( qKeyTime , SecretKey ) . toString ( ) ; // 步骤二：构成 FormatString var formatString = [ method , pathname , obj2str ( query ) , obj2str ( headers ) , '' ] . join ( '\n' ) ; // 步骤三：计算 StringToSign var stringToSign = [ 'sha1' , qSignTime , CryptoJS . SHA1 ( formatString ) . toString ( ) , '' ] . join ( '\n' ) ; // 步骤四：计算 Signature var qSignature = CryptoJS . HmacSHA1 ( stringToSign , signKey ) . toString ( ) ; // 步骤五：构造 Authorization var authorization = [ 'q-sign-algorithm=' + qSignAlgorithm , 'q-ak=' + qAk , 'q-sign-time=' + qSignTime , 'q-key-time=' + qKeyTime , 'q-header-list=' + qHeaderList , 'q-url-param-list=' + qUrlParamList , 'q-signature=' + qSignature ] . join ( '&' ) ; return authorization ; }


Input: 测试用的key后面可以去掉 [CODESPLIT] function ( opt ) { opt = opt || { } ; var SecretId = opt . SecretId ; var SecretKey = opt . SecretKey ; var method = ( opt . method || opt . Method || 'get' ) . toLowerCase ( ) ; var queryParams = clone ( opt . Query || opt . params || { } ) ; var headers = clone ( opt . Headers || opt . headers || { } ) ; var Key = opt . Key || '' ; var pathname ; if ( opt . UseRawKey ) { pathname = opt . Pathname || opt . pathname || '/' + Key ; } else { pathname = opt . Pathname || opt . pathname || Key ; pathname . indexOf ( '/' ) !== 0 && ( pathname = '/' + pathname ) ; } if ( ! SecretId ) return console . error ( 'missing param SecretId' ) ; if ( ! SecretKey ) return console . error ( 'missing param SecretKey' ) ; var getObjectKeys = function ( obj ) { var list = [ ] ; for ( var key in obj ) { if ( obj . hasOwnProperty ( key ) ) { list . push ( key ) ; } } return list . sort ( function ( a , b ) { a = a . toLowerCase ( ) ; b = b . toLowerCase ( ) ; return a === b ? 0 : ( a > b ? 1 : - 1 ) ; } ) ; } ; var obj2str = function ( obj ) { var i , key , val ; var list = [ ] ; var keyList = getObjectKeys ( obj ) ; for ( i = 0 ; i < keyList . length ; i ++ ) { key = keyList [ i ] ; val = ( obj [ key ] === undefined || obj [ key ] === null ) ? '' : ( '' + obj [ key ] ) ; key = key . toLowerCase ( ) ; key = camSafeUrlEncode ( key ) ; val = camSafeUrlEncode ( val ) || '' ; list . push ( key + '=' + val ) } return list . join ( '&' ) ; } ; // 签名有效起止时间 var now = Math . round ( getSkewTime ( opt . SystemClockOffset ) / 1000 ) - 1 ; var exp = now ; var Expires = opt . Expires || opt . expires ; if ( Expires === undefined ) { exp += 900 ; // 签名过期时间为当前 + 900s } else { exp += ( Expires * 1 ) || 0 ; } // 要用到的 Authorization 参数列表 var qSignAlgorithm = 'sha1' ; var qAk = SecretId ; var qSignTime = now + ';' + exp ; var qKeyTime = now + ';' + exp ; var qHeaderList = getObjectKeys ( headers ) . join ( ';' ) . toLowerCase ( ) ; var qUrlParamList = getObjectKeys ( queryParams ) . join ( ';' ) . toLowerCase ( ) ; // 签名算法说明文档：https://www.qcloud.com/document/product/436/7778 // 步骤一：计算 SignKey var signKey = CryptoJS . HmacSHA1 ( qKeyTime , SecretKey ) . toString ( ) ; // 步骤二：构成 FormatString var formatString = [ method , pathname , obj2str ( queryParams ) , obj2str ( headers ) , '' ] . join ( '\n' ) ; // 步骤三：计算 StringToSign var stringToSign = [ 'sha1' , qSignTime , CryptoJS . SHA1 ( formatString ) . toString ( ) , '' ] . join ( '\n' ) ; // 步骤四：计算 Signature var qSignature = CryptoJS . HmacSHA1 ( stringToSign , signKey ) . toString ( ) ; // 步骤五：构造 Authorization var authorization = [ 'q-sign-algorithm=' + qSignAlgorithm , 'q-ak=' + qAk , 'q-sign-time=' + qSignTime , 'q-key-time=' + qKeyTime , 'q-header-list=' + qHeaderList , 'q-url-param-list=' + qUrlParamList , 'q-signature=' + qSignature ] . join ( '&' ) ; return authorization ; }


Input: 清除对象里值为的 undefined 或 null 的属性 [CODESPLIT] function ( obj ) { var retObj = { } ; for ( var key in obj ) { if ( obj . hasOwnProperty ( key ) && obj [ key ] !== undefined && obj [ key ] !== null ) { retObj [ key ] = obj [ key ] ; } } return retObj ; }


Input: 获取文件 md5 值 [CODESPLIT] function ( blob , callback ) { readAsBinaryString ( blob , function ( content ) { var hash = md5 ( content , true ) ; callback ( null , hash ) ; } ) ; }


Input: 代理回调函数 [CODESPLIT] function ( result ) { if ( result && result . headers ) { result . headers [ 'x-cos-version-id' ] && ( result . VersionId = result . headers [ 'x-cos-version-id' ] ) ; result . headers [ 'x-cos-delete-marker' ] && ( result . DeleteMarker = result . headers [ 'x-cos-delete-marker' ] ) ; } return result ; }


Input: 获取上传任务的 UploadId [CODESPLIT] function getUploadIdAndPartList ( params , callback ) { var TaskId = params . TaskId ; var Bucket = params . Bucket ; var Region = params . Region ; var Key = params . Key ; var StorageClass = params . StorageClass ; var self = this ; // 计算 ETag var ETagMap = { } ; var FileSize = params . FileSize ; var SliceSize = params . SliceSize ; var SliceCount = Math . ceil ( FileSize / SliceSize ) ; var FinishSliceCount = 0 ; var FinishSize = 0 ; var onHashProgress = util . throttleOnProgress . call ( self , FileSize , params . onHashProgress ) ; var getChunkETag = function ( PartNumber , callback ) { var start = SliceSize * ( PartNumber - 1 ) ; var end = Math . min ( start + SliceSize , FileSize ) ; var ChunkSize = end - start ; if ( ETagMap [ PartNumber ] ) { callback ( null , { PartNumber : PartNumber , ETag : ETagMap [ PartNumber ] , Size : ChunkSize } ) ; } else { util . fileSlice ( params . Body , start , end , false , function ( chunkItem ) { util . getFileMd5 ( chunkItem , function ( err , md5 ) { if ( err ) return callback ( err ) ; var ETag = '"' + md5 + '"' ; ETagMap [ PartNumber ] = ETag ; FinishSliceCount += 1 ; FinishSize += ChunkSize ; callback ( err , { PartNumber : PartNumber , ETag : ETag , Size : ChunkSize } ) ; onHashProgress ( { loaded : FinishSize , total : FileSize } ) ; } ) ; } ) ; } } ; // 通过和文件的 md5 对比，判断 UploadId 是否可用 var isAvailableUploadList = function ( PartList , callback ) { var PartCount = PartList . length ; // 如果没有分片，通过 if ( PartCount === 0 ) { return callback ( null , true ) ; } // 检查分片数量 if ( PartCount > SliceCount ) { return callback ( null , false ) ; } // 检查分片大小 if ( PartCount > 1 ) { var PartSliceSize = Math . max ( PartList [ 0 ] . Size , PartList [ 1 ] . Size ) ; if ( PartSliceSize !== SliceSize ) { return callback ( null , false ) ; } } // 逐个分片计算并检查 ETag 是否一致 var next = function ( index ) { if ( index < PartCount ) { var Part = PartList [ index ] ; getChunkETag ( Part . PartNumber , function ( err , chunk ) { if ( chunk && chunk . ETag === Part . ETag && chunk . Size === Part . Size ) { next ( index + 1 ) ; } else { callback ( null , false ) ; } } ) ; } else { callback ( null , true ) ; } } ; next ( 0 ) ; } ; var ep = new EventProxy ( ) ; ep . on ( 'error' , function ( errData ) { if ( ! self . _isRunningTask ( TaskId ) ) return ; return callback ( errData ) ; } ) ; // 存在 UploadId ep . on ( 'upload_id_ready' , function ( UploadData ) { // 转换成 map var map = { } ; var list = [ ] ; util . each ( UploadData . PartList , function ( item ) { map [ item . PartNumber ] = item ; } ) ; for ( var PartNumber = 1 ; PartNumber <= SliceCount ; PartNumber ++ ) { var item = map [ PartNumber ] ; if ( item ) { item . PartNumber = PartNumber ; item . Uploaded = true ; } else { item = { PartNumber : PartNumber , ETag : null , Uploaded : false } ; } list . push ( item ) ; } UploadData . PartList = list ; callback ( null , UploadData ) ; } ) ; // 不存在 UploadId, 初始化生成 UploadId ep . on ( 'no_available_upload_id' , function ( ) { if ( ! self . _isRunningTask ( TaskId ) ) return ; var _params = util . extend ( { Bucket : Bucket , Region : Region , Key : Key , Headers : util . clone ( params . Headers ) , StorageClass : StorageClass , Body : params . Body , } , params ) ; // 获取 File 或 Blob 的 type 属性，如果有，作为文件 Content-Type var ContentType = params . Headers [ 'Content-Type' ] || ( params . Body && params . Body . type ) ; if ( ContentType ) { _params . Headers [ 'Content-Type' ] = ContentType ; } self . multipartInit ( _params , function ( err , data ) { if ( ! self . _isRunningTask ( TaskId ) ) return ; if ( err ) return ep . emit ( 'error' , err ) ; var UploadId = data . UploadId ; if ( ! UploadId ) { return callback ( { Message : 'no upload id' } ) ; } ep . emit ( 'upload_id_ready' , { UploadId : UploadId , PartList : [ ] } ) ; } ) ; } ) ; // 如果已存在 UploadId，找一个可以用的 UploadId ep . on ( 'has_upload_id' , function ( UploadIdList ) { // 串行地，找一个内容一致的 UploadId UploadIdList = UploadIdList . reverse ( ) ; Async . eachLimit ( UploadIdList , 1 , function ( UploadId , asyncCallback ) { if ( ! self . _isRunningTask ( TaskId ) ) return ; // 如果正在上传，跳过 if ( uploadIdUsing [ UploadId ] ) { asyncCallback ( ) ; // 检查下一个 UploadId return ; } // 判断 UploadId 是否可用 wholeMultipartListPart . call ( self , { Bucket : Bucket , Region : Region , Key : Key , UploadId : UploadId , } , function ( err , PartListData ) { if ( ! self . _isRunningTask ( TaskId ) ) return ; if ( err ) { removeUploadId . call ( self , UploadId ) ; return ep . emit ( 'error' , err ) ; } var PartList = PartListData . PartList ; PartList . forEach ( function ( item ) { item . PartNumber *= 1 ; item . Size *= 1 ; item . ETag = item . ETag || '' ; } ) ; isAvailableUploadList ( PartList , function ( err , isAvailable ) { if ( ! self . _isRunningTask ( TaskId ) ) return ; if ( err ) return ep . emit ( 'error' , err ) ; if ( isAvailable ) { asyncCallback ( { UploadId : UploadId , PartList : PartList } ) ; // 马上结束 } else { asyncCallback ( ) ; // 检查下一个 UploadId } } ) ; } ) ; } , function ( AvailableUploadData ) { if ( ! self . _isRunningTask ( TaskId ) ) return ; onHashProgress ( null , true ) ; if ( AvailableUploadData && AvailableUploadData . UploadId ) { ep . emit ( 'upload_id_ready' , AvailableUploadData ) ; } else { ep . emit ( 'no_available_upload_id' ) ; } } ) ; } ) ; // 在本地缓存找可用的 UploadId ep . on ( 'seek_local_avail_upload_id' , function ( RemoteUploadIdList ) { // 在本地找可用的 UploadId var uuid = util . getFileUUID ( params . Body , params . ChunkSize ) , LocalUploadIdList ; if ( uuid && ( LocalUploadIdList = getUploadId . call ( self , uuid ) ) ) { var next = function ( index ) { // 如果本地找不到可用 UploadId，再一个个遍历校验远端 if ( index >= LocalUploadIdList . length ) { ep . emit ( 'has_upload_id' , RemoteUploadIdList ) ; return ; } var UploadId = LocalUploadIdList [ index ] ; // 如果不在远端 UploadId 列表里，跳过并删除 if ( ! util . isInArray ( RemoteUploadIdList , UploadId ) ) { removeUploadId . call ( self , UploadId ) ; next ( index + 1 ) ; return ; } // 如果正在上传，跳过 if ( uploadIdUsing [ UploadId ] ) { next ( index + 1 ) ; return ; } // 判断 UploadId 是否存在线上 wholeMultipartListPart . call ( self , { Bucket : Bucket , Region : Region , Key : Key , UploadId : UploadId , } , function ( err , PartListData ) { if ( ! self . _isRunningTask ( TaskId ) ) return ; if ( err ) { removeUploadId . call ( self , UploadId ) ; next ( index + 1 ) ; } else { // 找到可用 UploadId ep . emit ( 'upload_id_ready' , { UploadId : UploadId , PartList : PartListData . PartList , } ) ; } } ) ; } ; next ( 0 ) ; } else { ep . emit ( 'has_upload_id' , RemoteUploadIdList ) ; } } ) ; // 获取线上 UploadId 列表 ep . on ( 'get_remote_upload_id_list' , function ( RemoteUploadIdList ) { // 获取符合条件的 UploadId 列表，因为同一个文件可以有多个上传任务。 wholeMultipartList . call ( self , { Bucket : Bucket , Region : Region , Key : Key , } , function ( err , data ) { if ( ! self . _isRunningTask ( TaskId ) ) return ; if ( err ) { return ep . emit ( 'error' , err ) ; } // 整理远端 UploadId 列表 var RemoteUploadIdList = util . filter ( data . UploadList , function ( item ) { return item . Key === Key && ( ! StorageClass || item . StorageClass . toUpperCase ( ) === StorageClass . toUpperCase ( ) ) ; } ) . reverse ( ) . map ( function ( item ) { return item . UploadId || item . UploadID ; } ) ; if ( RemoteUploadIdList . length ) { ep . emit ( 'seek_local_avail_upload_id' , RemoteUploadIdList ) ; } else { var uuid = util . getFileUUID ( params . Body , params . ChunkSize ) , LocalUploadIdList ; if ( uuid && ( LocalUploadIdList = getUploadId . call ( self , uuid ) ) ) { util . each ( LocalUploadIdList , function ( UploadId ) { removeUploadId . call ( self , UploadId ) ; } ) ; } ep . emit ( 'no_available_upload_id' ) ; } } ) ; } ) ; // 开始找可用 UploadId ep . emit ( 'get_remote_upload_id_list' ) ; }


Input: 通过和文件的 md5 对比，判断 UploadId 是否可用 [CODESPLIT] function ( PartList , callback ) { var PartCount = PartList . length ; // 如果没有分片，通过 if ( PartCount === 0 ) { return callback ( null , true ) ; } // 检查分片数量 if ( PartCount > SliceCount ) { return callback ( null , false ) ; } // 检查分片大小 if ( PartCount > 1 ) { var PartSliceSize = Math . max ( PartList [ 0 ] . Size , PartList [ 1 ] . Size ) ; if ( PartSliceSize !== SliceSize ) { return callback ( null , false ) ; } } // 逐个分片计算并检查 ETag 是否一致 var next = function ( index ) { if ( index < PartCount ) { var Part = PartList [ index ] ; getChunkETag ( Part . PartNumber , function ( err , chunk ) { if ( chunk && chunk . ETag === Part . ETag && chunk . Size === Part . Size ) { next ( index + 1 ) ; } else { callback ( null , false ) ; } } ) ; } else { callback ( null , true ) ; } } ; next ( 0 ) ; }


Input: 逐个分片计算并检查 ETag 是否一致 [CODESPLIT] function ( index ) { if ( index < PartCount ) { var Part = PartList [ index ] ; getChunkETag ( Part . PartNumber , function ( err , chunk ) { if ( chunk && chunk . ETag === Part . ETag && chunk . Size === Part . Size ) { next ( index + 1 ) ; } else { callback ( null , false ) ; } } ) ; } else { callback ( null , true ) ; } }


Input: 获取符合条件的全部上传任务 ( 条件包括 Bucket Region Prefix ) [CODESPLIT] function wholeMultipartList ( params , callback ) { var self = this ; var UploadList = [ ] ; var sendParams = { Bucket : params . Bucket , Region : params . Region , Prefix : params . Key } ; var next = function ( ) { self . multipartList ( sendParams , function ( err , data ) { if ( err ) return callback ( err ) ; UploadList . push . apply ( UploadList , data . Upload || [ ] ) ; if ( data . IsTruncated === 'true' ) { // 列表不完整 sendParams . KeyMarker = data . NextKeyMarker ; sendParams . UploadIdMarker = data . NextUploadIdMarker ; next ( ) ; } else { callback ( null , { UploadList : UploadList } ) ; } } ) ; } ; next ( ) ; }


Input: 获取指定上传任务的分块列表 [CODESPLIT] function wholeMultipartListPart ( params , callback ) { var self = this ; var PartList = [ ] ; var sendParams = { Bucket : params . Bucket , Region : params . Region , Key : params . Key , UploadId : params . UploadId } ; var next = function ( ) { self . multipartListPart ( sendParams , function ( err , data ) { if ( err ) return callback ( err ) ; PartList . push . apply ( PartList , data . Part || [ ] ) ; if ( data . IsTruncated === 'true' ) { // 列表不完整 sendParams . PartNumberMarker = data . NextPartNumberMarker ; next ( ) ; } else { callback ( null , { PartList : PartList } ) ; } } ) ; } ; next ( ) ; }


Input: 上传文件分块，包括 / * UploadId ( 上传任务编号 ) AsyncLimit ( 并发量 ) ， SliceList ( 上传的分块数组 ) ， FilePath ( 本地文件的位置 ) ， SliceSize ( 文件分块大小 ) FileSize ( 文件大小 ) onProgress ( 上传成功之后的回调函数 ) [CODESPLIT] function uploadSliceList ( params , cb ) { var self = this ; var TaskId = params . TaskId ; var Bucket = params . Bucket ; var Region = params . Region ; var Key = params . Key ; var UploadData = params . UploadData ; var FileSize = params . FileSize ; var SliceSize = params . SliceSize ; var ChunkParallel = Math . min ( params . AsyncLimit || self . options . ChunkParallelLimit || 1 , 256 ) ; var Body = params . Body ; var SliceCount = Math . ceil ( FileSize / SliceSize ) ; var FinishSize = 0 ; var ServerSideEncryption = params . ServerSideEncryption ; var needUploadSlices = util . filter ( UploadData . PartList , function ( SliceItem ) { if ( SliceItem [ 'Uploaded' ] ) { FinishSize += SliceItem [ 'PartNumber' ] >= SliceCount ? ( FileSize % SliceSize || SliceSize ) : SliceSize ; } return ! SliceItem [ 'Uploaded' ] ; } ) ; var onProgress = params . onProgress ; Async . eachLimit ( needUploadSlices , ChunkParallel , function ( SliceItem , asyncCallback ) { if ( ! self . _isRunningTask ( TaskId ) ) return ; var PartNumber = SliceItem [ 'PartNumber' ] ; var currentSize = Math . min ( FileSize , SliceItem [ 'PartNumber' ] * SliceSize ) - ( SliceItem [ 'PartNumber' ] - 1 ) * SliceSize ; var preAddSize = 0 ; uploadSliceItem . call ( self , { TaskId : TaskId , Bucket : Bucket , Region : Region , Key : Key , SliceSize : SliceSize , FileSize : FileSize , PartNumber : PartNumber , ServerSideEncryption : ServerSideEncryption , Body : Body , UploadData : UploadData , onProgress : function ( data ) { FinishSize += data . loaded - preAddSize ; preAddSize = data . loaded ; onProgress ( { loaded : FinishSize , total : FileSize } ) ; } , } , function ( err , data ) { if ( ! self . _isRunningTask ( TaskId ) ) return ; if ( util . isBrowser && ! err && ! data . ETag ) { err = 'get ETag error, please add "ETag" to CORS ExposeHeader setting.' ; } if ( err ) { FinishSize -= preAddSize ; } else { FinishSize += currentSize - preAddSize ; SliceItem . ETag = data . ETag ; } asyncCallback ( err || null , data ) ; } ) ; } , function ( err ) { if ( ! self . _isRunningTask ( TaskId ) ) return ; if ( err ) return cb ( err ) ; cb ( null , { UploadId : UploadData . UploadId , SliceList : UploadData . PartList } ) ; } ) ; }


Input: 完成分块上传 [CODESPLIT] function uploadSliceComplete ( params , callback ) { var Bucket = params . Bucket ; var Region = params . Region ; var Key = params . Key ; var UploadId = params . UploadId ; var SliceList = params . SliceList ; var self = this ; var ChunkRetryTimes = this . options . ChunkRetryTimes + 1 ; var Parts = SliceList . map ( function ( item ) { return { PartNumber : item . PartNumber , ETag : item . ETag } ; } ) ; // 完成上传的请求也做重试 Async . retry ( ChunkRetryTimes , function ( tryCallback ) { self . multipartComplete ( { Bucket : Bucket , Region : Region , Key : Key , UploadId : UploadId , Parts : Parts } , tryCallback ) ; } , function ( err , data ) { callback ( err , data ) ; } ) ; }


Input: 抛弃分块上传任务 / * AsyncLimit ( 抛弃上传任务的并发量 ) ， UploadId ( 上传任务的编号，当 Level 为 task 时候需要 ) Level ( 抛弃分块上传任务的级别，task : 抛弃指定的上传任务，file ： 抛弃指定的文件对应的上传任务，其他值 ：抛弃指定Bucket 的全部上传任务 ) [CODESPLIT] function abortUploadTask ( params , callback ) { var Bucket = params . Bucket ; var Region = params . Region ; var Key = params . Key ; var UploadId = params . UploadId ; var Level = params . Level || 'task' ; var AsyncLimit = params . AsyncLimit ; var self = this ; var ep = new EventProxy ( ) ; ep . on ( 'error' , function ( errData ) { return callback ( errData ) ; } ) ; // 已经获取到需要抛弃的任务列表 ep . on ( 'get_abort_array' , function ( AbortArray ) { abortUploadTaskArray . call ( self , { Bucket : Bucket , Region : Region , Key : Key , Headers : params . Headers , AsyncLimit : AsyncLimit , AbortArray : AbortArray } , function ( err , data ) { if ( err ) { return callback ( err ) ; } callback ( null , data ) ; } ) ; } ) ; if ( Level === 'bucket' ) { // Bucket 级别的任务抛弃，抛弃该 Bucket 下的全部上传任务 wholeMultipartList . call ( self , { Bucket : Bucket , Region : Region } , function ( err , data ) { if ( err ) { return callback ( err ) ; } ep . emit ( 'get_abort_array' , data . UploadList || [ ] ) ; } ) ; } else if ( Level === 'file' ) { // 文件级别的任务抛弃，抛弃该文件的全部上传任务 if ( ! Key ) return callback ( { error : 'abort_upload_task_no_key' } ) ; wholeMultipartList . call ( self , { Bucket : Bucket , Region : Region , Key : Key } , function ( err , data ) { if ( err ) { return callback ( err ) ; } ep . emit ( 'get_abort_array' , data . UploadList || [ ] ) ; } ) ; } else if ( Level === 'task' ) { // 单个任务级别的任务抛弃，抛弃指定 UploadId 的上传任务 if ( ! UploadId ) return callback ( { error : 'abort_upload_task_no_id' } ) ; if ( ! Key ) return callback ( { error : 'abort_upload_task_no_key' } ) ; ep . emit ( 'get_abort_array' , [ { Key : Key , UploadId : UploadId } ] ) ; } else { return callback ( { error : 'abort_unknown_level' } ) ; } }


Input: 批量抛弃分块上传任务 [CODESPLIT] function abortUploadTaskArray ( params , callback ) { var Bucket = params . Bucket ; var Region = params . Region ; var Key = params . Key ; var AbortArray = params . AbortArray ; var AsyncLimit = params . AsyncLimit || 1 ; var self = this ; var index = 0 ; var resultList = new Array ( AbortArray . length ) ; Async . eachLimit ( AbortArray , AsyncLimit , function ( AbortItem , callback ) { var eachIndex = index ; if ( Key && Key !== AbortItem . Key ) { resultList [ eachIndex ] = { error : { KeyNotMatch : true } } ; callback ( null ) ; return ; } var UploadId = AbortItem . UploadId || AbortItem . UploadID ; self . multipartAbort ( { Bucket : Bucket , Region : Region , Key : AbortItem . Key , Headers : params . Headers , UploadId : UploadId } , function ( err , data ) { var task = { Bucket : Bucket , Region : Region , Key : AbortItem . Key , UploadId : UploadId } ; resultList [ eachIndex ] = { error : err , task : task } ; callback ( null ) ; } ) ; index ++ ; } , function ( err ) { if ( err ) { return callback ( err ) ; } var successList = [ ] ; var errorList = [ ] ; for ( var i = 0 , len = resultList . length ; i < len ; i ++ ) { var item = resultList [ i ] ; if ( item [ 'task' ] ) { if ( item [ 'error' ] ) { errorList . push ( item [ 'task' ] ) ; } else { successList . push ( item [ 'task' ] ) ; } } } return callback ( null , { successList : successList , errorList : errorList } ) ; } ) ; }


Input: 分片复制文件 [CODESPLIT] function sliceCopyFile ( params , callback ) { var ep = new EventProxy ( ) ; var self = this ; var Bucket = params . Bucket ; var Region = params . Region ; var Key = params . Key ; var CopySource = params . CopySource ; var m = CopySource . match ( / ^([^.]+-\d+)\.cos(v6)?\.([^.]+)\.[^/]+\/(.+)$ / ) ; if ( ! m ) { callback ( { error : 'CopySource format error' } ) ; return ; } var SourceBucket = m [ 1 ] ; var SourceRegion = m [ 3 ] ; var SourceKey = decodeURIComponent ( m [ 4 ] ) ; var CopySliceSize = params . SliceSize === undefined ? self . options . CopySliceSize : params . SliceSize ; CopySliceSize = Math . max ( 0 , Math . min ( CopySliceSize , 5 * 1024 * 1024 * 1024 ) ) ; var ChunkSize = params . ChunkSize || this . options . CopyChunkSize ; var ChunkParallel = this . options . CopyChunkParallelLimit ; var FinishSize = 0 ; var FileSize ; var onProgress ; // 分片复制完成，开始 multipartComplete 操作 ep . on ( 'copy_slice_complete' , function ( UploadData ) { self . multipartComplete ( { Bucket : Bucket , Region : Region , Key : Key , UploadId : UploadData . UploadId , Parts : UploadData . PartList , } , function ( err , data ) { if ( err ) { onProgress ( null , true ) ; return callback ( err ) ; } onProgress ( { loaded : FileSize , total : FileSize } , true ) ; callback ( null , data ) ; } ) ; } ) ; ep . on ( 'get_copy_data_finish' , function ( UploadData ) { Async . eachLimit ( UploadData . PartList , ChunkParallel , function ( SliceItem , asyncCallback ) { var PartNumber = SliceItem . PartNumber ; var CopySourceRange = SliceItem . CopySourceRange ; var currentSize = SliceItem . end - SliceItem . start ; var preAddSize = 0 ; copySliceItem . call ( self , { Bucket : Bucket , Region : Region , Key : Key , CopySource : CopySource , UploadId : UploadData . UploadId , PartNumber : PartNumber , CopySourceRange : CopySourceRange , onProgress : function ( data ) { FinishSize += data . loaded - preAddSize ; preAddSize = data . loaded ; onProgress ( { loaded : FinishSize , total : FileSize } ) ; } } , function ( err , data ) { if ( err ) { return asyncCallback ( err ) ; } onProgress ( { loaded : FinishSize , total : FileSize } ) ; FinishSize += currentSize - preAddSize ; SliceItem . ETag = data . ETag ; asyncCallback ( err || null , data ) ; } ) ; } , function ( err ) { if ( err ) { onProgress ( null , true ) ; return callback ( err ) ; } ep . emit ( 'copy_slice_complete' , UploadData ) ; } ) ; } ) ; ep . on ( 'get_file_size_finish' , function ( SourceHeaders ) { // 控制分片大小 ( function ( ) { var SIZE = [ 1 , 2 , 4 , 8 , 16 , 32 , 64 , 128 , 256 , 512 , 1024 , 1024 * 2 , 1024 * 4 , 1024 * 5 ] ; var AutoChunkSize = 1024 * 1024 ; for ( var i = 0 ; i < SIZE . length ; i ++ ) { AutoChunkSize = SIZE [ i ] * 1024 * 1024 ; if ( FileSize / AutoChunkSize <= self . options . MaxPartNumber ) break ; } params . ChunkSize = ChunkSize = Math . max ( ChunkSize , AutoChunkSize ) ; var ChunkCount = Math . ceil ( FileSize / ChunkSize ) ; var list = [ ] ; for ( var partNumber = 1 ; partNumber <= ChunkCount ; partNumber ++ ) { var start = ( partNumber - 1 ) * ChunkSize ; var end = partNumber * ChunkSize < FileSize ? ( partNumber * ChunkSize - 1 ) : FileSize - 1 ; var item = { PartNumber : partNumber , start : start , end : end , CopySourceRange : "bytes=" + start + "-" + end , } ; list . push ( item ) ; } params . PartList = list ; } ) ( ) ; var TargetHeader ; if ( params . Headers [ 'x-cos-metadata-directive' ] === 'Replaced' ) { TargetHeader = params . Headers ; } else { TargetHeader = SourceHeaders ; } TargetHeader [ 'x-cos-storage-class' ] = params . Headers [ 'x-cos-storage-class' ] || SourceHeaders [ 'x-cos-storage-class' ] ; TargetHeader = util . clearKey ( TargetHeader ) ; self . multipartInit ( { Bucket : Bucket , Region : Region , Key : Key , Headers : TargetHeader , } , function ( err , data ) { if ( err ) { return callback ( err ) ; } params . UploadId = data . UploadId ; ep . emit ( 'get_copy_data_finish' , params ) ; } ) ; } ) ; // 获取远端复制源文件的大小 self . headObject ( { Bucket : SourceBucket , Region : SourceRegion , Key : SourceKey , } , function ( err , data ) { if ( err ) { if ( err . statusCode && err . statusCode === 404 ) { callback ( { ErrorStatus : SourceKey + ' Not Exist' } ) ; } else { callback ( err ) ; } return ; } FileSize = params . FileSize = data . headers [ 'content-length' ] ; if ( FileSize === undefined || ! FileSize ) { callback ( { error : 'get Content-Length error, please add "Content-Length" to CORS ExposeHeader setting.' } ) ; return ; } onProgress = util . throttleOnProgress . call ( self , FileSize , params . onProgress ) ; // 开始上传 if ( FileSize <= CopySliceSize ) { if ( ! params . Headers [ 'x-cos-metadata-directive' ] ) { params . Headers [ 'x-cos-metadata-directive' ] = 'Copy' ; } self . putObjectCopy ( params , function ( err , data ) { if ( err ) { onProgress ( null , true ) ; return callback ( err ) ; } onProgress ( { loaded : FileSize , total : FileSize } , true ) ; callback ( err , data ) ; } ) ; } else { var resHeaders = data . headers ; var SourceHeaders = { 'Cache-Control' : resHeaders [ 'cache-control' ] , 'Content-Disposition' : resHeaders [ 'content-disposition' ] , 'Content-Encoding' : resHeaders [ 'content-encoding' ] , 'Content-Type' : resHeaders [ 'content-type' ] , 'Expires' : resHeaders [ 'expires' ] , 'x-cos-storage-class' : resHeaders [ 'x-cos-storage-class' ] , } ; util . each ( resHeaders , function ( v , k ) { var metaPrefix = 'x-cos-meta-' ; if ( k . indexOf ( metaPrefix ) === 0 && k . length > metaPrefix . length ) { SourceHeaders [ k ] = v ; } } ) ; ep . emit ( 'get_file_size_finish' , SourceHeaders ) ; } } ) ; }


Input: 复制指定分片 [CODESPLIT] function copySliceItem ( params , callback ) { var TaskId = params . TaskId ; var Bucket = params . Bucket ; var Region = params . Region ; var Key = params . Key ; var CopySource = params . CopySource ; var UploadId = params . UploadId ; var PartNumber = params . PartNumber * 1 ; var CopySourceRange = params . CopySourceRange ; var ChunkRetryTimes = this . options . ChunkRetryTimes + 1 ; var self = this ; Async . retry ( ChunkRetryTimes , function ( tryCallback ) { self . uploadPartCopy ( { TaskId : TaskId , Bucket : Bucket , Region : Region , Key : Key , CopySource : CopySource , UploadId : UploadId , PartNumber : PartNumber , CopySourceRange : CopySourceRange , onProgress : params . onProgress , } , function ( err , data ) { tryCallback ( err || null , data ) ; } ) } , function ( err , data ) { return callback ( err , data ) ; } ) ; }


Input: If already stringified - return original content [CODESPLIT] function stringify ( content ) { if ( typeof content === 'string' && stringifiedRegexp . test ( content ) ) { return content ; } return JSON . stringify ( content , null , 2 ) ; }


Input: Find nearest module chunk ( not sure that is reliable method but who cares ) . [CODESPLIT] function getModuleChunk ( module , modules ) { let chunks ; if ( webpackVersion . IS_4 ) { chunks = Array . from ( module . chunksIterable ) ; } else if ( parseInt ( webpackVersion ( ) , 10 ) >= 3 ) { chunks = module . mapChunks ( ) ; } else { chunks = module . chunks ; } // webpack 1 compat const issuer = typeof module . issuer === 'string' ? modules . find ( m => m . request === module . issuer ) : module . issuer ; if ( Array . isArray ( chunks ) && chunks . length > 0 ) { return chunks [ chunks . length - 1 ] ; } else if ( issuer ) { return getModuleChunk ( issuer , modules ) ; } return null ; }


Input: webpack 1 compat loader options finder . Returns normalized options . [CODESPLIT] function getLoaderOptions ( loaderPath , rule ) { let multiRuleProp ; if ( isWebpack1 ) { multiRuleProp = 'loaders' ; } else if ( rule . oneOf ) { multiRuleProp = 'oneOf' ; } else { multiRuleProp = 'use' ; } const multiRule = typeof rule === 'object' && Array . isArray ( rule [ multiRuleProp ] ) ? rule [ multiRuleProp ] : null ; let options ; if ( multiRule ) { const rules = [ ] . concat ( ... multiRule . map ( r => ( r . use || r ) ) ) ; options = rules . map ( normalizeRule ) . find ( r => loaderPath . includes ( r . loader ) ) . options ; } else { options = normalizeRule ( rule ) . options ; } return options ; }


Input: webpack 1 compat rule normalizer [CODESPLIT] function normalizeRule ( rule ) { if ( ! rule ) { throw new Error ( 'Rule should be string or object' ) ; } let data ; if ( typeof rule === 'string' ) { const parts = rule . split ( '?' ) ; data = { loader : parts [ 0 ] , options : parts [ 1 ] ? parseQuery ( ` ${ parts [ 1 ] } ` ) : null } ; } else { const options = isWebpack1 ? rule . query : rule . options ; data = { loader : rule . loader , options : options || null } ; } return data ; }


Input: find child excluding dragging node default [CODESPLIT] function findChild ( info , children , handler , reverse ) { const len = children . length if ( reverse ) { for ( let i = len - 1 ; i >= 0 ; i -- ) { const item = children [ i ] // excluding dragging node if ( item !== info . node ) { if ( handler ( item , i ) ) { return item } } } } else { for ( let i = 0 ; i < len ; i ++ ) { const item = children [ i ] // excluding dragging node if ( item !== info . node ) { if ( handler ( item , i ) ) { return item } } } } }


Input: start from node self [CODESPLIT] function findParent ( node , handle ) { let current = node while ( current ) { if ( handle ( current ) ) { return current } current = current . parent } }


Input: pure node self [CODESPLIT] function pure ( node , withChildren , after ) { var _this2 = this ; var t = assign$1 ( { } , node ) ; delete t . _id ; delete t . parent ; delete t . children ; delete t . open ; delete t . active ; delete t . style ; delete t . class ; delete t . innerStyle ; delete t . innerClass ; delete t . innerBackStyle ; delete t . innerBackClass ; var _arr = keys$1 ( t ) ; for ( var _i = 0 ; _i < _arr . length ; _i ++ ) { var key = _arr [ _i ] ; if ( key [ 0 ] === '_' ) { delete t [ key ] ; } } if ( withChildren && node . children ) { t . children = node . children . slice ( ) ; t . children . forEach ( function ( v , k ) { t . children [ k ] = _this2 . pure ( v , withChildren ) ; } ) ; } if ( after ) { return after ( t , node ) || t ; } return t ; }


Input: find child excluding dragging node default [CODESPLIT] function findChild ( info , children , handler , reverse ) { var len = children . length ; if ( reverse ) { for ( var i = len - 1 ; i >= 0 ; i -- ) { var item = children [ i ] ; // excluding dragging node if ( item !== info . node ) { if ( handler ( item , i ) ) { return item ; } } } } else { for ( var _i = 0 ; _i < len ; _i ++ ) { var _item = children [ _i ] ; // excluding dragging node if ( _item !== info . node ) { if ( handler ( _item , _i ) ) { return _item ; } } } } }


Input: 当前树为空 ( 不包括占位节点 ) [CODESPLIT] function currentTreeEmpty ( info ) { return ! findChild ( info , info . currentTree . rootData . children , function ( v ) { return v ; } ) ; }


Input: 另一节点有子 ( 不包括占位节点 ) [CODESPLIT] function targetNodeHasChildrenExcludingPlaceholder ( info ) { return findChild ( info , info . targetNode . children , function ( v ) { return v !== info . dplh ; } ) ; }


Input: 另一节点是第一个节点 [CODESPLIT] function targetNodeIs1stChild ( info ) { return findChild ( info , info . targetNode . parent . children , function ( v ) { return v ; } ) === info . targetNode ; }


Input: 另一节点是最后节点 [CODESPLIT] function targetNodeIsLastChild ( info ) { return findChild ( info , info . targetNode . parent . children , function ( v ) { return v ; } , true ) === info . targetNode ; }


Input: 当前位置在另一节点innner indent位置右边 [CODESPLIT] function atIndentRight ( info ) { return info . offset . x > info . tiOffset . x + info . currentTree . indent ; }


Input: context is vm [CODESPLIT] function autoMoveDragPlaceHolder ( draggableHelperInfo ) { var trees = this . store . trees ; var dhStore = draggableHelperInfo . store ; // make info var info = { event : draggableHelperInfo . event , el : dhStore . el , vm : this , node : this . data , store : this . store , dplh : this . store . dplh , draggableHelperData : { opt : draggableHelperInfo . options , store : dhStore } // } ; attachCache ( info , new Cache ( ) , { // dragging node coordinate // 拖动中的节点相关坐标 nodeInnerEl : function nodeInnerEl ( ) { return this . el . querySelector ( '.tree-node-inner' ) ; } , offset : function offset ( ) { return getOffset ( this . nodeInnerEl ) ; } , // left top point offset2 : function offset2 ( ) { return { x : this . offset . x + this . nodeInnerEl . offsetWidth , y : this . offset . y + this . nodeInnerEl . offsetHeight } ; } , // right bottom point offsetToViewPort : function offsetToViewPort ( ) { var r = this . nodeInnerEl . getBoundingClientRect ( ) ; r . x = r . left ; r . y = r . top ; return r ; } , // tree currentTree : function currentTree ( ) { // const currentTree = trees.find(tree => hp.isOffsetInEl(this.offset.x, this.offset.y, tree.$el)) var currentTree = getTreeByPoint ( this . offsetToViewPort . x , this . offsetToViewPort . y , trees ) ; if ( currentTree ) { var dragStartTree = this . store ; if ( prevTree == null ) { prevTree = dragStartTree ; } if ( prevTree !== currentTree ) { if ( ! isPropTrue ( dragStartTree . crossTree ) || ! isPropTrue ( currentTree . crossTree ) ) { return ; } prevTree = currentTree ; } if ( ! isPropTrue ( currentTree . droppable ) ) { return ; } return currentTree ; } } , currentTreeRootEl : function currentTreeRootEl ( ) { return document . getElementById ( this . currentTree . rootData . _id ) ; } , currentTreeRootOf4 : function currentTreeRootOf4 ( ) { return getOf4 ( this . currentTreeRootEl , this . currentTree . space ) ; } , // the second child of currentTree root, excluding dragging node currentTreeRootSecondChildExcludingDragging : function currentTreeRootSecondChildExcludingDragging ( ) { var _this = this ; return this . currentTree . rootData . children . slice ( 0 , 3 ) . filter ( function ( v ) { return v !== _this . node ; } ) [ 1 ] ; } , // placeholder dplhEl : function dplhEl ( ) { return document . getElementById ( this . dplh . _id ) ; } , dplhElInCurrentTree : function dplhElInCurrentTree ( ) { return Boolean ( this . currentTree . $el . querySelector ( "#" . concat ( this . dplh . _id ) ) ) ; } , dplhOf4 : function dplhOf4 ( ) { return getOf4 ( this . dplhEl , this . currentTree . space ) ; } , dplhAtTop : function dplhAtTop ( ) { return Math . abs ( this . dplhOf4 . y - this . currentTreeRootOf4 . y ) < 5 ; } , targetAtTop : function targetAtTop ( ) { return Math . abs ( this . tiOf4 . y - this . currentTreeRootOf4 . y ) < 5 ; } , targetAtBottom : function targetAtBottom ( ) { return Math . abs ( this . tiOf4 . y2 - this . currentTreeRootOf4 . y2 ) < 5 ; } , // most related node // 最相关的另一个节点 targetNode : function targetNode ( ) { var currentTree = this . currentTree ; if ( ! currentTree ) { throw 'no currentTree' ; } // var _this$offset = this . offset , x = _this$offset . x , y = _this$offset . y ; var currentNode = currentTree . rootData ; while ( true ) { var children = currentNode . children ; if ( ! children ) { break ; } if ( this . node . parent === currentNode ) { // dragging node is in currentNode children, remove it first children = children . slice ( ) ; children . splice ( children . indexOf ( this . node ) , 1 ) ; } if ( children . length === 0 ) { break ; } var t = binarySearch ( children , function ( node ) { var el = document . getElementById ( node . _id ) ; var ty = getOffset ( el ) . y ; var ty2 = ty + el . offsetHeight + currentTree . space ; if ( ty2 < y ) { return - 1 ; } else if ( ty <= y ) { return 0 ; } else { return 1 ; } } , null , null , true ) ; if ( t . hit ) { currentNode = t . value ; } else { if ( t . bigger ) { currentNode = children [ t . index - 1 ] ; } else { currentNode = t . value ; } } if ( ! currentNode ) { currentNode = children [ 0 ] ; break ; } if ( ! currentNode ) { break ; } var innerEl = document . getElementById ( currentNode . _id ) . querySelector ( '.tree-node-inner' ) ; var of = getOf4 ( innerEl , currentTree . space ) ; if ( of . y <= y && y <= of . y2 ) { break ; } } return currentNode ; } , targetNodeEl : function targetNodeEl ( ) { return document . getElementById ( this . targetNode . _id ) ; } , // targetNodeInnerElOffset tiInnerEl : function tiInnerEl ( ) { return this . targetNodeEl . querySelector ( '.tree-node-inner' ) ; } , tiOffset : function tiOffset ( ) { return getOffset ( this . tiInnerEl ) ; } , tiOf4 : function tiOf4 ( ) { return getOf4 ( this . tiInnerEl , this . currentTree . space ) ; } , tiMiddleY : function tiMiddleY ( ) { return this . tiOffset . y + this . tiInnerEl . offsetHeight / 2 ; } , // targetPrevEl : function targetPrevEl ( ) { // tree node 之间不要有其他元素, 否则这里会获取到错误的元素 var r = this . targetNodeEl . previousSibling ; if ( hasClass ( r , 'dragging' ) ) { r = r . previousSibling ; } return r ; } , targetPrev : function targetPrev ( ) { var id = this . targetPrevEl . getAttribute ( 'id' ) ; return this . currentTree . getNodeById ( id ) ; } } ) ; // attachCache end // decision start ================================= var executedRuleCache = { } ; // exec rule var exec = function exec ( ruleId ) { if ( ! executedRuleCache . hasOwnProperty ( ruleId ) ) { var r ; try { r = rules [ ruleId ] ( info ) ; } catch ( e ) { r = e ; try { if ( process . env . DEVELOPE_SELF ) { // only visible when develop its self console . warn ( "failed to execute rule '" . concat ( ruleId , "'" ) , e ) ; } } catch ( e2 ) { } } executedRuleCache [ ruleId ] = r ; } return executedRuleCache [ ruleId ] ; } ; if ( exec ( 'currentTree existed' ) === true ) { if ( exec ( 'targetNode is placeholder' ) === false ) { if ( exec ( 'targetNode is the second child of root' ) === true ) { if ( exec ( 'targetNode has children excluding placeholder' ) === false ) { if ( exec ( 'on targetNode middle' ) === true ) { targets [ 'before' ] ( info ) ; } else if ( exec ( 'on targetNode middle' ) === false ) { if ( exec ( 'at indent right' ) === true ) { targets [ 'append' ] ( info ) ; } else if ( exec ( 'at indent right' ) === false ) { targets [ 'after' ] ( info ) ; } } } else if ( exec ( 'targetNode has children excluding placeholder' ) === true ) { targets [ 'prepend' ] ( info ) ; } } else if ( exec ( 'targetNode is the second child of root' ) === false ) { if ( exec ( 'currentTree empty' ) === false ) { if ( exec ( 'targetNode at top' ) === true ) { if ( exec ( 'placeholder in currentTree' ) === true ) { if ( exec ( 'targetNode has children excluding placeholder' ) === false ) { if ( exec ( 'on targetNode middle' ) === false ) { if ( exec ( 'at indent right' ) === false ) { targets [ 'after' ] ( info ) ; } else if ( exec ( 'at indent right' ) === true ) { targets [ 'append' ] ( info ) ; } } else if ( exec ( 'on targetNode middle' ) === true ) { targets [ 'before' ] ( info ) ; } } else if ( exec ( 'targetNode has children excluding placeholder' ) === true ) { if ( exec ( 'on targetNode middle' ) === false ) { targets [ 'prepend' ] ( info ) ; } else if ( exec ( 'on targetNode middle' ) === true ) { targets [ 'before' ] ( info ) ; } } } else if ( exec ( 'placeholder in currentTree' ) === false ) { targets [ 'before' ] ( info ) ; } } else if ( exec ( 'targetNode at top' ) === false ) { if ( exec ( 'targetNode at bottom' ) === false ) { if ( exec ( 'placeholder at top' ) === true ) { targets [ 'prepend' ] ( info ) ; } else if ( exec ( 'placeholder at top' ) === false ) { if ( exec ( 'targetNode has children excluding placeholder' ) === true ) { targets [ 'prepend' ] ( info ) ; } else if ( exec ( 'targetNode has children excluding placeholder' ) === false ) { if ( exec ( 'targetNode is 1st child' ) === false ) { if ( exec ( 'targetNode is last child' ) === false ) { if ( exec ( 'on targetNode middle' ) === true ) { if ( exec ( 'at indent right' ) === true ) { targets [ 'append' ] ( info ) ; } else if ( exec ( 'at indent right' ) === false ) { targets [ 'after' ] ( info ) ; } } else if ( exec ( 'on targetNode middle' ) === false ) { if ( exec ( 'at indent right' ) === true ) { targets [ 'append' ] ( info ) ; } else if ( exec ( 'at indent right' ) === false ) { targets [ 'after' ] ( info ) ; } } } else if ( exec ( 'targetNode is last child' ) === true ) { if ( exec ( 'at indent right' ) === true ) { targets [ 'append' ] ( info ) ; } else if ( exec ( 'at indent right' ) === false ) { targets [ 'after' ] ( info ) ; } } } else if ( exec ( 'targetNode is 1st child' ) === true ) { if ( exec ( 'targetNode is last child' ) === true ) { targets [ 'append' ] ( info ) ; } else if ( exec ( 'targetNode is last child' ) === false ) { if ( exec ( 'on targetNode middle' ) === false ) { if ( exec ( 'at indent right' ) === false ) { targets [ 'after' ] ( info ) ; } else if ( exec ( 'at indent right' ) === true ) { targets [ 'append' ] ( info ) ; } } else if ( exec ( 'on targetNode middle' ) === true ) { if ( exec ( 'at indent right' ) === false ) { targets [ 'after' ] ( info ) ; } else if ( exec ( 'at indent right' ) === true ) { targets [ 'append' ] ( info ) ; } } } } } } } else if ( exec ( 'targetNode at bottom' ) === true ) { if ( exec ( 'placeholder in currentTree' ) === true ) { if ( exec ( 'on targetNode middle' ) === false ) { if ( exec ( 'at indent right' ) === true ) { targets [ 'append' ] ( info ) ; } else if ( exec ( 'at indent right' ) === false ) { targets [ 'after' ] ( info ) ; } } else if ( exec ( 'on targetNode middle' ) === true ) { targets [ 'append' ] ( info ) ; } } else if ( exec ( 'placeholder in currentTree' ) === false ) { targets [ 'append' ] ( info ) ; } } } } else if ( exec ( 'currentTree empty' ) === true ) { targets [ 'append current tree' ] ( info ) ; } } } else if ( exec ( 'targetNode is placeholder' ) === true ) { if ( exec ( 'targetNode at bottom' ) === false ) { if ( exec ( 'targetNode is the second child of root' ) === false ) { if ( exec ( 'targetNode is 1st child' ) === true ) { if ( exec ( 'targetNode is last child' ) === false ) ; else if ( exec ( 'targetNode is last child' ) === true ) { if ( exec ( 'on targetNode middle' ) === false ) { if ( exec ( 'at left' ) === true ) { targets [ 'after target parent' ] ( info ) ; } else if ( exec ( 'at left' ) === false ) ; } else if ( exec ( 'on targetNode middle' ) === true ) { if ( exec ( 'at left' ) === true ) { targets [ 'after target parent' ] ( info ) ; } else if ( exec ( 'at left' ) === false ) ; } } } else if ( exec ( 'targetNode is 1st child' ) === false ) { if ( exec ( 'targetNode is last child' ) === true ) { if ( exec ( 'on targetNode middle' ) === true ) { if ( exec ( 'at left' ) === true ) { targets [ 'after target parent' ] ( info ) ; } else if ( exec ( 'at left' ) === false ) { if ( exec ( 'at indent right' ) === true ) { targets [ 'append prev' ] ( info ) ; } else if ( exec ( 'at indent right' ) === false ) ; } } else if ( exec ( 'on targetNode middle' ) === false ) { if ( exec ( 'at left' ) === true ) { targets [ 'after target parent' ] ( info ) ; } else if ( exec ( 'at left' ) === false ) { if ( exec ( 'at indent right' ) === true ) { targets [ 'append prev' ] ( info ) ; } else if ( exec ( 'at indent right' ) === false ) ; } } } else if ( exec ( 'targetNode is last child' ) === false ) { if ( exec ( 'on targetNode middle' ) === true ) { if ( exec ( 'at left' ) === true ) ; else if ( exec ( 'at left' ) === false ) { if ( exec ( 'at indent right' ) === true ) { targets [ 'append prev' ] ( info ) ; } else if ( exec ( 'at indent right' ) === false ) ; } } else if ( exec ( 'on targetNode middle' ) === false ) { if ( exec ( 'at left' ) === true ) ; else if ( exec ( 'at left' ) === false ) { if ( exec ( 'at indent right' ) === true ) { targets [ 'append prev' ] ( info ) ; } else if ( exec ( 'at indent right' ) === false ) ; } } } } } else if ( exec ( 'targetNode is the second child of root' ) === true ) { if ( exec ( 'on targetNode middle' ) === true ) { if ( exec ( 'at indent right' ) === true ) { targets [ 'append prev' ] ( info ) ; } else if ( exec ( 'at indent right' ) === false ) ; } else if ( exec ( 'on targetNode middle' ) === false ) { if ( exec ( 'at indent right' ) === true ) { targets [ 'append prev' ] ( info ) ; } else if ( exec ( 'at indent right' ) === false ) ; } } } else if ( exec ( 'targetNode at bottom' ) === true ) { if ( exec ( 'targetNode is 1st child' ) === true ) { if ( exec ( 'on targetNode middle' ) === false ) { if ( exec ( 'at left' ) === true ) { targets [ 'after target parent' ] ( info ) ; } else if ( exec ( 'at left' ) === false ) ; } else if ( exec ( 'on targetNode middle' ) === true ) { if ( exec ( 'at left' ) === false ) ; else if ( exec ( 'at left' ) === true ) { targets [ 'after target parent' ] ( info ) ; } } } else if ( exec ( 'targetNode is 1st child' ) === false ) { if ( exec ( 'on targetNode middle' ) === false ) { if ( exec ( 'at left' ) === true ) { targets [ 'after target parent' ] ( info ) ; } else if ( exec ( 'at left' ) === false ) { if ( exec ( 'at indent right' ) === true ) { targets [ 'append prev' ] ( info ) ; } else if ( exec ( 'at indent right' ) === false ) ; } } else if ( exec ( 'on targetNode middle' ) === true ) { if ( exec ( 'at left' ) === true ) { targets [ 'after target parent' ] ( info ) ; } else if ( exec ( 'at left' ) === false ) { if ( exec ( 'at indent right' ) === true ) { targets [ 'append prev' ] ( info ) ; } else if ( exec ( 'at indent right' ) === false ) ; } } } } } } else if ( exec ( 'currentTree existed' ) === false ) ; // decision end ================================= // }


Input: left top point [CODESPLIT] function offset2 ( ) { return { x : this . offset . x + this . nodeInnerEl . offsetWidth , y : this . offset . y + this . nodeInnerEl . offsetHeight } ; }


Input: right bottom point [CODESPLIT] function offsetToViewPort ( ) { var r = this . nodeInnerEl . getBoundingClientRect ( ) ; r . x = r . left ; r . y = r . top ; return r ; }


Input: the second child of currentTree root excluding dragging node [CODESPLIT] function currentTreeRootSecondChildExcludingDragging ( ) { var _this = this ; return this . currentTree . rootData . children . slice ( 0 , 3 ) . filter ( function ( v ) { return v !== _this . node ; } ) [ 1 ] ; }


Input: exec rule [CODESPLIT] function exec ( ruleId ) { if ( ! executedRuleCache . hasOwnProperty ( ruleId ) ) { var r ; try { r = rules [ ruleId ] ( info ) ; } catch ( e ) { r = e ; try { if ( process . env . DEVELOPE_SELF ) { // only visible when develop its self console . warn ( "failed to execute rule '" . concat ( ruleId , "'" ) , e ) ; } } catch ( e2 ) { } } executedRuleCache [ ruleId ] = r ; } return executedRuleCache [ ruleId ] ; }


Input: append to prev sibling [CODESPLIT] function appendPrev ( info ) { if ( isNodeDroppable ( info . targetPrev ) ) { th . appendTo ( info . dplh , info . targetPrev ) ; if ( ! info . targetPrev . open ) info . store . toggleOpen ( info . targetPrev ) ; } else { insertDplhAfterTo ( info . dplh , info . targetPrev , info ) ; } }


Input: append to current tree [CODESPLIT] function appendCurrentTree ( info ) { if ( isNodeDroppable ( info . currentTree . rootData ) ) { th . appendTo ( info . dplh , info . currentTree . rootData ) ; } }


Input: tree [CODESPLIT] function currentTree ( ) { // const currentTree = trees.find(tree => hp.isOffsetInEl(this.offset.x, this.offset.y, tree.$el)) var currentTree = getTreeByPoint ( this . offsetToViewPort . x , this . offsetToViewPort . y , trees ) ; if ( currentTree ) { var dragStartTree = this . store ; if ( prevTree == null ) { prevTree = dragStartTree ; } if ( prevTree !== currentTree ) { if ( ! vf . isPropTrue ( dragStartTree . crossTree ) || ! vf . isPropTrue ( currentTree . crossTree ) ) { return ; } prevTree = currentTree ; } if ( ! vf . isPropTrue ( currentTree . droppable ) ) { return ; } return currentTree ; } }


Input: most related node 最相关的另一个节点 [CODESPLIT] function targetNode ( ) { var currentTree = this . currentTree ; if ( ! currentTree ) { throw 'no currentTree' ; } // var _this$offset = this . offset , x = _this$offset . x , y = _this$offset . y ; var currentNode = currentTree . rootData ; while ( true ) { var children = currentNode . children ; if ( ! children ) { break ; } if ( this . node . parent === currentNode ) { // dragging node is in currentNode children, remove it first children = children . slice ( ) ; children . splice ( children . indexOf ( this . node ) , 1 ) ; } if ( children . length === 0 ) { break ; } var t = hp . binarySearch ( children , function ( node ) { var el = document . getElementById ( node . _id ) ; var ty = hp . getOffset ( el ) . y ; var ty2 = ty + el . offsetHeight + currentTree . space ; if ( ty2 < y ) { return - 1 ; } else if ( ty <= y ) { return 0 ; } else { return 1 ; } } , null , null , true ) ; if ( t . hit ) { currentNode = t . value ; } else { if ( t . bigger ) { currentNode = children [ t . index - 1 ] ; } else { currentNode = t . value ; } } if ( ! currentNode ) { currentNode = children [ 0 ] ; break ; } if ( ! currentNode ) { break ; } var innerEl = document . getElementById ( currentNode . _id ) . querySelector ( '.tree-node-inner' ) ; var of = getOf4 ( innerEl , currentTree . space ) ; if ( of . y <= y && y <= of . y2 ) { break ; } } return currentNode ; }


Input: Check if the word View is appended to selector and if it is strip it out [CODESPLIT] function stripViewFromSelector ( selector ) { // Don't strip it out if it's one of these 4 element types // (see https://github.com/facebook/WebDriverAgent/blob/master/WebDriverAgentLib/Utilities/FBElementTypeTransformer.m for reference) const keepView = [ 'XCUIElementTypeScrollView' , 'XCUIElementTypeCollectionView' , 'XCUIElementTypeTextView' , 'XCUIElementTypeWebView' , ] . includes ( selector ) ; if ( ! keepView && selector . indexOf ( 'View' ) === selector . length - 4 ) { return selector . substr ( 0 , selector . length - 4 ) ; } else { return selector ; } }


Input: Get the process id of the most recent running application having the particular command line pattern . [CODESPLIT] async function getPidUsingPattern ( pgrepPattern ) { const args = [ '-nif' , pgrepPattern ] ; try { const { stdout } = await exec ( 'pgrep' , args ) ; const pid = parseInt ( stdout , 10 ) ; if ( isNaN ( pid ) ) { log . debug ( ` ${ args . join ( ' ' ) } ${ stdout } ` ) ; return null ; } return ` ${ pid } ` ; } catch ( err ) { log . debug ( ` ${ args . join ( ' ' ) } ${ err . code } ` ) ; return null ; } }


Input: Kill a process having the particular command line pattern . This method tries to send SIGINT SIGTERM and SIGKILL to the matched processes in this order if the process is still running . [CODESPLIT] async function killAppUsingPattern ( pgrepPattern ) { for ( const signal of [ 2 , 15 , 9 ] ) { if ( ! await getPidUsingPattern ( pgrepPattern ) ) { return ; } const args = [ ` ${ signal } ` , '-if' , pgrepPattern ] ; try { await exec ( 'pkill' , args ) ; } catch ( err ) { log . debug ( ` ${ args . join ( ' ' ) } ${ err . message } ` ) ; } await B . delay ( 100 ) ; } }


Input: Get the IDs of processes listening on the particular system port . It is also possible to apply additional filtering based on the process command line . [CODESPLIT] async function getPIDsListeningOnPort ( port , filteringFunc = null ) { const result = [ ] ; try { // This only works since Mac OS X El Capitan const { stdout } = await exec ( 'lsof' , [ '-ti' , ` ${ port } ` ] ) ; result . push ( ... ( stdout . trim ( ) . split ( / \n+ / ) ) ) ; } catch ( e ) { return result ; } if ( ! _ . isFunction ( filteringFunc ) ) { return result ; } return await B . filter ( result , async ( x ) => { const { stdout } = await exec ( 'ps' , [ '-p' , x , '-o' , 'command' ] ) ; return await filteringFunc ( stdout ) ; } ) ; }


Input: @typedef { Object } UploadOptions [CODESPLIT] async function encodeBase64OrUpload ( localFile , remotePath = null , uploadOptions = { } ) { if ( ! await fs . exists ( localFile ) ) { log . errorAndThrow ( ` ${ localFile } ` ) ; } const { size } = await fs . stat ( localFile ) ; log . debug ( ` ${ util . toReadableSizeString ( size ) } ` ) ; if ( _ . isEmpty ( remotePath ) ) { const maxMemoryLimit = v8 . getHeapStatistics ( ) . total_available_size / 2 ; if ( size >= maxMemoryLimit ) { log . info ( ` ` + ` ${ util . toReadableSizeString ( size ) } ${ util . toReadableSizeString ( maxMemoryLimit ) } ` + ` ` + ` ` ) ; } const content = await fs . readFile ( localFile ) ; return content . toString ( 'base64' ) ; } const remoteUrl = url . parse ( remotePath ) ; let options = { } ; const { user , pass , method } = uploadOptions ; if ( remoteUrl . protocol . startsWith ( 'http' ) ) { options = { url : remoteUrl . href , method : method || 'PUT' , multipart : [ { body : _fs . createReadStream ( localFile ) } ] , } ; if ( user && pass ) { options . auth = { user , pass } ; } } else if ( remoteUrl . protocol === 'ftp:' ) { options = { host : remoteUrl . hostname , port : remoteUrl . port || 21 , } ; if ( user && pass ) { options . user = user ; options . pass = pass ; } } await net . uploadFile ( localFile , remotePath , options ) ; return '' ; }


Input: Stops and removes all web socket handlers that are listening in scope of the currect session . [CODESPLIT] async function removeAllSessionWebSocketHandlers ( server , sessionId ) { if ( ! server || ! _ . isFunction ( server . getWebSocketHandlers ) ) { return ; } const activeHandlers = await server . getWebSocketHandlers ( sessionId ) ; for ( const pathname of _ . keys ( activeHandlers ) ) { await server . removeWebSocketHandler ( pathname ) ; } }


Input: Verify whether the given application is compatible to the platform where it is going to be installed and tested . [CODESPLIT] async function verifyApplicationPlatform ( app , isSimulator ) { log . debug ( 'Verifying application platform' ) ; const infoPlist = path . resolve ( app , 'Info.plist' ) ; if ( ! await fs . exists ( infoPlist ) ) { log . debug ( ` ${ infoPlist } ` ) ; return null ; } const { CFBundleSupportedPlatforms } = await plist . parsePlistFile ( infoPlist ) ; log . debug ( ` ${ JSON . stringify ( CFBundleSupportedPlatforms ) } ` ) ; if ( ! _ . isArray ( CFBundleSupportedPlatforms ) ) { log . debug ( ` ${ infoPlist } ` ) ; return null ; } const isAppSupported = ( isSimulator && CFBundleSupportedPlatforms . includes ( 'iPhoneSimulator' ) ) || ( ! isSimulator && CFBundleSupportedPlatforms . includes ( 'iPhoneOS' ) ) ; if ( isAppSupported ) { return true ; } throw new Error ( ` ${ isSimulator ? 'Simulator' : 'Real device' } ${ app } ` + ` ` ) ; }


Input: Returns true if the urlString is localhost [CODESPLIT] function isLocalHost ( urlString ) { try { const { hostname } = url . parse ( urlString ) ; return [ 'localhost' , '127.0.0.1' , '::1' , '::ffff:127.0.0.1' ] . includes ( hostname ) ; } catch { log . warn ( ` ${ urlString } ` ) ; } return false ; }


Input: Normalizes platformVersion to a valid iOS version string [CODESPLIT] function normalizePlatformVersion ( originalVersion ) { const normalizedVersion = util . coerceVersion ( originalVersion , false ) ; if ( ! normalizedVersion ) { throw new Error ( ` ${ originalVersion } ` ) ; } const { major , minor } = new semver . SemVer ( normalizedVersion ) ; return ` ${ major } ${ minor } ` ; }


Input: Update WebDriverAgentRunner project bundle ID with newBundleId . This method assumes project file is in the correct state . [CODESPLIT] async function updateProjectFile ( agentPath , newBundleId ) { let projectFilePath = ` ${ agentPath } ${ PROJECT_FILE } ` ; try { // Assuming projectFilePath is in the correct state, create .old from projectFilePath await fs . copyFile ( projectFilePath , ` ${ projectFilePath } ` ) ; await replaceInFile ( projectFilePath , new RegExp ( WDA_RUNNER_BUNDLE_ID . replace ( '.' , '\.' ) , 'g' ) , newBundleId ) ; // eslint-disable-line no-useless-escape log . debug ( ` ${ projectFilePath } ${ newBundleId } ` ) ; } catch ( err ) { log . debug ( ` ${ err . message } ` ) ; log . warn ( ` ${ projectFilePath } ` + ` ${ newBundleId } ` ) ; } }


Input: Reset WebDriverAgentRunner project bundle ID to correct state . [CODESPLIT] async function resetProjectFile ( agentPath ) { let projectFilePath = ` ${ agentPath } ${ PROJECT_FILE } ` ; try { // restore projectFilePath from .old file if ( ! await fs . exists ( ` ${ projectFilePath } ` ) ) { return ; // no need to reset } await fs . mv ( ` ${ projectFilePath } ` , projectFilePath ) ; log . debug ( ` ${ projectFilePath } ${ WDA_RUNNER_BUNDLE_ID } ` ) ; } catch ( err ) { log . debug ( ` ${ err . message } ` ) ; log . warn ( ` ${ projectFilePath } ` + ` ${ WDA_RUNNER_BUNDLE_ID } ` + ` ` ) ; } }


Input: Return the WDA object which appends existing xctest runner content [CODESPLIT] function getAdditionalRunContent ( platformName , wdaRemotePort ) { const runner = ` ${ isTvOS ( platformName ) ? '_tvOS' : '' } ` ; return { [ runner ] : { EnvironmentVariables : { USE_PORT : wdaRemotePort } } } ; }


Input: Retrieves WDA upgrade timestamp [CODESPLIT] async function getWDAUpgradeTimestamp ( bootstrapPath ) { const carthageRootPath = path . resolve ( bootstrapPath , CARTHAGE_ROOT ) ; if ( await fs . exists ( carthageRootPath ) ) { const { mtime } = await fs . stat ( carthageRootPath ) ; return mtime . getTime ( ) ; } return null ; }


Input: Generates Apple s over - the - air configuration profile for certificate deployment based on the given PEM certificate content . Read https : // developer . apple . com / library / content / documentation / NetworkingInternet / Conceptual / iPhoneOTAConfiguration / Introduction / Introduction . html for more details on such profiles . [CODESPLIT] function toMobileConfig ( certBuffer , commonName ) { const getUUID = ( ) => UUID . create ( ) . hex . toUpperCase ( ) ; const contentUuid = getUUID ( ) ; return { PayloadContent : [ { PayloadCertificateFileName : ` ${ commonName } ` , PayloadContent : certBuffer , PayloadDescription : 'Adds a CA root certificate' , PayloadDisplayName : commonName , PayloadIdentifier : ` ${ contentUuid } ` , PayloadType : 'com.apple.security.root' , PayloadUUID : contentUuid , PayloadVersion : 1 } ] , PayloadDisplayName : commonName , PayloadIdentifier : ` ${ os . hostname ( ) . split ( '.' ) [ 0 ] } ${ getUUID ( ) } ` , PayloadRemovalDisallowed : false , PayloadType : 'Configuration' , PayloadUUID : getUUID ( ) , PayloadVersion : 1 } ; }