{"action":"created","comment":{"url":"https://api.github.com/repos/cocos-creator/engine/pulls/comments/285948868","pull_request_review_id":239918238,"id":285948868,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDI4NTk0ODg2OA==","diff_hunk":"@@ -1,1032 +1,1054 @@\n-/****************************************************************************\n- Copyright (c) 2013-2016 Chukong Technologies Inc.\n- Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.\n-\n- http://www.cocos.com\n-\n- Permission is hereby granted, free of charge, to any person obtaining a copy\n- of this software and associated engine source code (the \"Software\"), a limited,\n-  worldwide, royalty-free, non-assignable, revocable and non-exclusive license\n- to use Cocos Creator solely to develop games on your target platforms. You shall\n-  not use Cocos Creator software for developing other software or tools that's\n-  used for developing games. You are not granted to publish, distribute,\n-  sublicense, and/or sell copies of Cocos Creator.\n-\n- The software or tools in this License Agreement are licensed, not sold.\n- Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.\n-\n- THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n- THE SOFTWARE.\n- ****************************************************************************/\n-\n-import { createMap, getClassName, isChildClassOf } from '../core/utils/js';\n-import { callInNextTick } from '../core/utils/misc';\n-import Pipeline from './pipeline';\n-import LoadingItems from './loading-items';\n-import AssetLoader from './asset-loader';\n-import Downloader from './downloader';\n-import Loader from './loader';\n-import AssetTable from './asset-table';\n-import { getDependsRecursively } from './auto-release-utils';\n-import ReleasedAssetChecker from './released-asset-checker';\n-\n-var assetTables = Object.create(null);\n-assetTables.assets = new AssetTable();\n-assetTables.internal = new AssetTable();\n-\n-function getXMLHttpRequest() {\n-    return window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject('MSXML2.XMLHTTP');\n-}\n-\n-var _info = { url: null, raw: false };\n-\n-// Convert a resources by finding its real url with uuid, otherwise we will use the uuid or raw url as its url\n-// So we gurantee there will be url in result\n-function getResWithUrl(res) {\n-    var id, result, isUuid;\n-    if (typeof res === 'object') {\n-        result = res;\n-        if (res.url) {\n-            return result;\n-        }\n-        else {\n-            id = res.uuid;\n-        }\n-    }\n-    else {\n-        result = {};\n-        id = res;\n-    }\n-    isUuid = result.type ? result.type === 'uuid' : cc.AssetLibrary._uuidInSettings(id);\n-    cc.AssetLibrary._getAssetInfoInRuntime(id, _info);\n-    result.url = !isUuid ? id : _info.url;\n-    if (_info.url && result.type === 'uuid' && _info.raw) {\n-        result.type = null;\n-        result.isRawAsset = true;\n-    }\n-    else if (!isUuid) {\n-        result.isRawAsset = true;\n-    }\n-    return result;\n-}\n-\n-var _sharedResources = [];\n-var _sharedList = [];\n-\n-/**\n- * Loader for resource loading process. It's a singleton object.\n- * @class loader\n- * @extends Pipeline\n- * @static\n- */\n-class CCLoader extends Pipeline {\n-    constructor() {\n-        var assetLoader = new AssetLoader();\n-        var downloader = new Downloader();\n-        var loader = new Loader();\n-\n-        super([\n-            assetLoader,\n-            downloader,\n-            loader\n-        ]);\n-\n-        /**\n-         * The asset loader in cc.loader's pipeline, it's by default the first pipe.\n-         * It's used to identify an asset's type, and determine how to download it.\n-         * @property assetLoader\n-         * @type {Object}\n-         */\n-        this.assetLoader = assetLoader;\n-\n-        /**\n-         * The md5 pipe in cc.loader's pipeline, it could be absent if the project isn't build with md5 option.\n-         * It's used to modify the url to the real downloadable url with md5 suffix.\n-         * @property md5Pipe\n-         * @type {Object}\n-         */\n-        this.md5Pipe = null;\n-\n-        /**\n-         * The downloader in cc.loader's pipeline, it's by default the second pipe.\n-         * It's used to download files with several handlers: pure text, image, script, audio, font, uuid.\n-         * You can add your own download function with addDownloadHandlers\n-         * @property downloader\n-         * @type {Object}\n-         */\n-        this.downloader = downloader;\n-\n-        /**\n-         * The loader in cc.loader's pipeline, it's by default the third pipe.\n-         * It's used to parse downloaded content with several handlers: JSON, image, plist, fnt, uuid.\n-         * You can add your own download function with addLoadHandlers\n-         * @property loader\n-         * @type {Object}\n-         */\n-        this.loader = loader;\n-\n-        this.onProgress = null;\n-\n-        this._assetTables = assetTables;\n-        // assets to release automatically\n-        this._autoReleaseSetting = createMap(true);\n-\n-        if (CC_DEBUG) {\n-            this._releasedAssetChecker_DEBUG = new ReleasedAssetChecker();\n-        }\n-    }\n-\n-    init(director) {\n-        if (CC_DEBUG) {\n-            var self = this;\n-            director.on(cc.Director.EVENT_AFTER_UPDATE, function () {\n-                self._releasedAssetChecker_DEBUG.checkCouldRelease(self._cache);\n-            });\n-        }\n-    }\n-\n-    /**\n-     * Add custom supported types handler or modify existing type handler for download process.\n-     * @example\n-     *  cc.loader.addDownloadHandlers({\n-     *      // This will match all url with `.scene` extension or all url with `scene` type\n-     *      'scene' : function (url, callback) {}\n-     *  });\n-     * @method addDownloadHandlers\n-     * @param {Object} extMap Custom supported types with corresponded handler\n-     */\n-    addDownloadHandlers(extMap) {\n-        this.downloader.addHandlers(extMap);\n-    }\n-\n-    /**\n-     * Add custom supported types handler or modify existing type handler for load process.\n-     * @example\n-     *  cc.loader.addLoadHandlers({\n-     *      // This will match all url with `.scene` extension or all url with `scene` type\n-     *      'scene' : function (url, callback) {}\n-     *  });\n-     * @method addLoadHandlers\n-     * @param {Object} extMap Custom supported types with corresponded handler\n-     */\n-    addLoadHandlers(extMap) {\n-        this.loader.addHandlers(extMap);\n-    }\n-\n-    /**\n-     * Load resources with a progression callback and a complete callback.\n-     * The progression callback is the same as Pipeline's {{#crossLink \"LoadingItems/onProgress:method\"}}onProgress{{/crossLink}}\n-     * The complete callback is almost the same as Pipeline's {{#crossLink \"LoadingItems/onComplete:method\"}}onComplete{{/crossLink}}\n-     * The only difference is when user pass a single url as resources, the complete callback will set its result directly as the second parameter.\n-     *\n-     * @example\n-     * cc.loader.load('a.png', function (err, tex) {\n-     *     cc.log('Result should be a texture: ' + (tex instanceof cc.Texture2D));\n-     * });\n-     *\n-     * cc.loader.load('http://example.com/a.png', function (err, tex) {\n-     *     cc.log('Should load a texture from external url: ' + (tex instanceof cc.Texture2D));\n-     * });\n-     *\n-     * cc.loader.load({url: 'http://example.com/getImageREST?file=a.png', type: 'png'}, function (err, tex) {\n-     *     cc.log('Should load a texture from RESTful API by specify the type: ' + (tex instanceof cc.Texture2D));\n-     * });\n-     *\n-     * cc.loader.load(['a.png', 'b.json'], function (errors, results) {\n-     *     if (errors) {\n-     *         for (var i = 0; i < errors.length; i++) {\n-     *             cc.log('Error url [' + errors[i] + ']: ' + results.getError(errors[i]));\n-     *         }\n-     *     }\n-     *     var aTex = results.getContent('a.png');\n-     *     var bJsonObj = results.getContent('b.json');\n-     * });\n-     *\n-     * @method load\n-     * @param {String|String[]|Object} resources - Url list in an array\n-     * @param {Function} [progressCallback] - Callback invoked when progression change\n-     * @param {Number} progressCallback.completedCount - The number of the items that are already completed\n-     * @param {Number} progressCallback.totalCount - The total number of the items\n-     * @param {Object} progressCallback.item - The latest item which flow out the pipeline\n-     * @param {Function} [completeCallback] - Callback invoked when all resources loaded\n-     * @typescript\n-     * load(resources: string|string[]|{uuid?: string, url?: string, type?: string}, completeCallback?: Function): void\n-     * load(resources: string|string[]|{uuid?: string, url?: string, type?: string}, progressCallback: (completedCount: number, totalCount: number, item: any) => void, completeCallback: Function|null): void\n-     */\n-    load(resources, progressCallback, completeCallback) {\n-        if (CC_DEV && !resources) {\n-            return cc.error(\"[cc.loader.load] resources must be non-nil.\");\n-        }\n-\n-        if (completeCallback === undefined) {\n-            completeCallback = progressCallback;\n-            progressCallback = this.onProgress || null;\n-        }\n-\n-        var self = this;\n-        var singleRes = false;\n-        var res;\n-        if (!(resources instanceof Array)) {\n-            if (resources) {\n-                singleRes = true;\n-                resources = [resources];\n-            } else {\n-                resources = [];\n-            }\n-        }\n-\n-        _sharedResources.length = 0;\n-        for (var i = 0; i < resources.length; ++i) {\n-            var resource = resources[i];\n-            // Backward compatibility\n-            if (resource && resource.id) {\n-                cc.warnID(4920, resource.id);\n-                if (!resource.uuid && !resource.url) {\n-                    resource.url = resource.id;\n-                }\n-            }\n-            res = getResWithUrl(resource);\n-            if (!res.url && !res.uuid)\n-                continue;\n-            var item = this._cache[res.url];\n-            _sharedResources.push(item || res);\n-        }\n-\n-        var queue = LoadingItems.create(this, progressCallback, function (errors, items) {\n-            callInNextTick(function () {\n-                if (completeCallback) {\n-                    if (singleRes) {\n-                        let id = res.url;\n-                        completeCallback.call(self, items.getError(id), items.getContent(id));\n-                    }\n-                    else {\n-                        completeCallback.call(self, errors, items);\n-                    }\n-                    completeCallback = null;\n-                }\n-\n-                items.destroy();\n-            });\n-        });\n-        LoadingItems.initQueueDeps(queue);\n-        queue.append(_sharedResources);\n-        _sharedResources.length = 0;\n-    }\n-\n-    flowInDeps(owner, urlList, callback) {\n-        _sharedList.length = 0;\n-        for (var i = 0; i < urlList.length; ++i) {\n-            var res = getResWithUrl(urlList[i]);\n-            if (!res.url && !res.uuid)\n-                continue;\n-            var item = this._cache[res.url];\n-            if (item) {\n-                _sharedList.push(item);\n-            }\n-            else {\n-                _sharedList.push(res);\n-            }\n-        }\n-\n-        var queue = LoadingItems.create(this, owner ? function (completedCount, totalCount, item) {\n-            if (this._ownerQueue && this._ownerQueue.onProgress) {\n-                this._ownerQueue._childOnProgress(item);\n-            }\n-        } : null, function (errors, items) {\n-            callback(errors, items);\n-            // Clear deps because it's already done\n-            // Each item will only flowInDeps once, so it's still safe here\n-            owner && owner.deps && (owner.deps.length = 0);\n-            items.destroy();\n-        });\n-        if (owner) {\n-            var ownerQueue = LoadingItems.getQueue(owner);\n-            // Set the root ownerQueue, if no ownerQueue defined in ownerQueue, it's the root\n-            queue._ownerQueue = ownerQueue._ownerQueue || ownerQueue;\n-        }\n-        var accepted = queue.append(_sharedList, owner);\n-        _sharedList.length = 0;\n-        return accepted;\n-    }\n-\n-    _getResUuid(url, type, mount, quiet) {\n-        mount = mount || 'assets';\n-        var assetTable = assetTables[mount];\n-        if (!url || !assetTable) {\n-            return null;\n-        }\n-        // Ignore parameter\n-        var index = url.indexOf('?');\n-        if (index !== -1)\n-            url = url.substr(0, index);\n-        var uuid = assetTable.getUuid(url, type);\n-        if (!uuid) {\n-            var extname = cc.path.extname(url);\n-            if (extname) {\n-                // strip extname\n-                url = url.slice(0, - extname.length);\n-                uuid = assetTable.getUuid(url, type);\n-                if (uuid && !quiet) {\n-                    cc.warnID(4901, url, extname);\n-                }\n-            }\n-        }\n-        return uuid;\n-    }\n-    // Find the asset's reference id in loader, asset could be asset object, asset uuid or asset url\n-    _getReferenceKey(assetOrUrlOrUuid) {\n-        var key;\n-        if (typeof assetOrUrlOrUuid === 'object') {\n-            key = assetOrUrlOrUuid._uuid || null;\n-        }\n-        else if (typeof assetOrUrlOrUuid === 'string') {\n-            key = this._getResUuid(assetOrUrlOrUuid, null, null, true) || assetOrUrlOrUuid;\n-        }\n-        if (!key) {\n-            cc.warnID(4800, assetOrUrlOrUuid);\n-            return key;\n-        }\n-        cc.AssetLibrary._getAssetInfoInRuntime(key, _info);\n-        return this._cache[_info.url] ? _info.url : key;\n-    }\n-\n-    _urlNotFound(url, type, completeCallback) {\n-        callInNextTick(function () {\n-            url = cc.url.normalize(url);\n-            var info = `${type ? getClassName(type) : 'Asset'} in \"resources/${url}\" does not exist.`;\n-            if (completeCallback) {\n-                completeCallback(new Error(info), []);\n-            }\n-        });\n-    }\n-\n-    /**\n-     * @param {Function} [type]\n-     * @param {Function} [onProgress]\n-     * @param {Function} onComplete\n-     * @returns {Object} arguments\n-     * @returns {Function} arguments.type\n-     * @returns {Function} arguments.onProgress\n-     * @returns {Function} arguments.onComplete\n-     */\n-    _parseLoadResArgs(type, onProgress, onComplete) {\n-        if (onComplete === undefined) {\n-            var isValidType = isChildClassOf(type, cc.RawAsset);\n-            if (onProgress) {\n-                onComplete = onProgress;\n-                if (isValidType) {\n-                    onProgress = this.onProgress || null;\n-                }\n-            }\n-            else if (onProgress === undefined && !isValidType) {\n-                onComplete = type;\n-                onProgress = this.onProgress || null;\n-                type = null;\n-            }\n-            if (onProgress !== undefined && !isValidType) {\n-                onProgress = type;\n-                type = null;\n-            }\n-        }\n-        return {\n-            type: type,\n-            onProgress: onProgress,\n-            onComplete: onComplete,\n-        };\n-    }\n-\n-    /**\n-     * Load resources from the \"resources\" folder inside the \"assets\" folder of your project.<br>\n-     * <br>\n-     * Note: All asset URLs in Creator use forward slashes, URLs using backslashes will not work.\n-     *\n-     * @method loadRes\n-     * @param {String} url - Url of the target resource.\n-     *                       The url is relative to the \"resources\" folder, extensions must be omitted.\n-     * @param {Function} [type] - Only asset of type will be loaded if this argument is supplied.\n-     * @param {Function} [progressCallback] - Callback invoked when progression change.\n-     * @param {Number} progressCallback.completedCount - The number of the items that are already completed.\n-     * @param {Number} progressCallback.totalCount - The total number of the items.\n-     * @param {Object} progressCallback.item - The latest item which flow out the pipeline.\n-     * @param {Function} [completeCallback] - Callback invoked when the resource loaded.\n-     * @param {Error} completeCallback.error - The error info or null if loaded successfully.\n-     * @param {Object} completeCallback.resource - The loaded resource if it can be found otherwise returns null.\n-     *\n-     * @example\n-     *\n-     * // load the prefab (project/assets/resources/misc/character/cocos) from resources folder\n-     * cc.loader.loadRes('misc/character/cocos', function (err, prefab) {\n-     *     if (err) {\n-     *         cc.error(err.message || err);\n-     *         return;\n-     *     }\n-     *     cc.log('Result should be a prefab: ' + (prefab instanceof cc.Prefab));\n-     * });\n-     *\n-     * // load the sprite frame of (project/assets/resources/imgs/cocos.png) from resources folder\n-     * cc.loader.loadRes('imgs/cocos', cc.SpriteFrame, function (err, spriteFrame) {\n-     *     if (err) {\n-     *         cc.error(err.message || err);\n-     *         return;\n-     *     }\n-     *     cc.log('Result should be a sprite frame: ' + (spriteFrame instanceof cc.SpriteFrame));\n-     * });\n-     * @typescript\n-     * loadRes(url: string, type: typeof cc.Asset, progressCallback: (completedCount: number, totalCount: number, item: any) => void, completeCallback: ((error: Error, resource: any) => void)|null): void\n-     * loadRes(url: string, type: typeof cc.Asset, completeCallback: (error: Error, resource: any) => void): void\n-     * loadRes(url: string, type: typeof cc.Asset): void\n-     * loadRes(url: string, progressCallback: (completedCount: number, totalCount: number, item: any) => void, completeCallback: ((error: Error, resource: any) => void)|null): void\n-     * loadRes(url: string, completeCallback: (error: Error, resource: any) => void): void\n-     * loadRes(url: string): void\n-     */\n-    loadRes(url, type, mount, progressCallback, completeCallback) {\n-        if (arguments.length !== 5) {\n-            completeCallback = progressCallback;\n-            progressCallback = mount;\n-            mount = 'assets';\n-        }\n-        var args = this._parseLoadResArgs(type, progressCallback, completeCallback);\n-        type = args.type;\n-        progressCallback = args.onProgress;\n-        completeCallback = args.onComplete;\n-        var self = this;\n-        var uuid = self._getResUuid(url, type, mount);\n-        if (uuid) {\n-            this.load(\n-                {\n-                    type: 'uuid',\n-                    uuid: uuid\n-                },\n-                progressCallback,\n-                function (err, asset) {\n-                    if (asset) {\n-                        // should not release these assets, even if they are static referenced in the scene.\n-                        self.setAutoReleaseRecursively(uuid, false);\n-                    }\n-                    if (completeCallback) {\n-                        completeCallback(err, asset);\n-                    }\n-                }\n-            );\n-        }\n-        else {\n-            self._urlNotFound(url, type, completeCallback);\n-        }\n-    }\n-\n-    _loadResUuids(uuids, progressCallback, completeCallback, urls) {\n-        if (uuids.length > 0) {\n-            var self = this;\n-            var res = uuids.map(function (uuid) {\n-                return {\n-                    type: 'uuid',\n-                    uuid: uuid\n-                }\n-            });\n-            this.load(res, progressCallback, function (errors, items) {\n-                if (completeCallback) {\n-                    var assetRes = [];\n-                    var urlRes = urls && [];\n-                    for (var i = 0; i < res.length; ++i) {\n-                        var uuid = res[i].uuid;\n-                        var id = this._getReferenceKey(uuid);\n-                        var item = items.getContent(id);\n-                        if (item) {\n-                            // should not release these assets, even if they are static referenced in the scene.\n-                            self.setAutoReleaseRecursively(uuid, false);\n-                            assetRes.push(item);\n-                            if (urlRes) {\n-                                urlRes.push(urls[i]);\n-                            }\n-                        }\n-                    }\n-                    if (urls) {\n-                        completeCallback(errors, assetRes, urlRes);\n-                    }\n-                    else {\n-                        completeCallback(errors, assetRes);\n-                    }\n-                }\n-            });\n-        }\n-        else {\n-            if (completeCallback) {\n-                callInNextTick(function () {\n-                    if (urls) {\n-                        completeCallback(null, [], []);\n-                    }\n-                    else {\n-                        completeCallback(null, []);\n-                    }\n-                });\n-            }\n-        }\n-    }\n-\n-    /**\n-     * This method is like {{#crossLink \"loader/loadRes:method\"}}{{/crossLink}} except that it accepts array of url.\n-     *\n-     * @method loadResArray\n-     * @param {String[]} urls - Array of URLs of the target resource.\n-     *                          The url is relative to the \"resources\" folder, extensions must be omitted.\n-     * @param {Function} [type] - Only asset of type will be loaded if this argument is supplied.\n-     * @param {Function} [progressCallback] - Callback invoked when progression change.\n-     * @param {Number} progressCallback.completedCount - The number of the items that are already completed.\n-     * @param {Number} progressCallback.totalCount - The total number of the items.\n-     * @param {Object} progressCallback.item - The latest item which flow out the pipeline.\n-     * @param {Function} [completeCallback] - A callback which is called when all assets have been loaded, or an error occurs.\n-     * @param {Error} completeCallback.error - If one of the asset failed, the complete callback is immediately called\n-     *                                         with the error. If all assets are loaded successfully, error will be null.\n-     * @param {Asset[]|Array} completeCallback.assets - An array of all loaded assets.\n-     *                                                     If nothing to load, assets will be an empty array.\n-     * @example\n-     *\n-     * // load the SpriteFrames from resources folder\n-     * var spriteFrames;\n-     * var urls = ['misc/characters/character_01', 'misc/weapons/weapons_01'];\n-     * cc.loader.loadResArray(urls, cc.SpriteFrame, function (err, assets) {\n-     *     if (err) {\n-     *         cc.error(err);\n-     *         return;\n-     *     }\n-     *     spriteFrames = assets;\n-     *     // ...\n-     * });\n-     * @typescript\n-     * loadResArray(url: string[], type: typeof cc.Asset, progressCallback: (completedCount: number, totalCount: number, item: any) => void, completeCallback: ((error: Error, resource: any[]) => void)|null): void\n-     * loadResArray(url: string[], type: typeof cc.Asset, completeCallback: (error: Error, resource: any[]) => void): void\n-     * loadResArray(url: string[], type: typeof cc.Asset): void\n-     * loadResArray(url: string[], progressCallback: (completedCount: number, totalCount: number, item: any) => void, completeCallback: ((error: Error, resource: any[]) => void)|null): void\n-     * loadResArray(url: string[], completeCallback: (error: Error, resource: any[]) => void): void\n-     * loadResArray(url: string[]): void\n-     */\n-    loadResArray(urls, type, mount, progressCallback, completeCallback) {\n-        if (arguments.length !== 5) {\n-            completeCallback = progressCallback;\n-            progressCallback = mount;\n-            mount = 'assets';\n-        }\n-\n-        var args = this._parseLoadResArgs(type, progressCallback, completeCallback);\n-        type = args.type;\n-        progressCallback = args.onProgress;\n-        completeCallback = args.onComplete;\n-\n-        var uuids = [];\n-        for (var i = 0; i < urls.length; i++) {\n-            var url = urls[i];\n-            var uuid = this._getResUuid(url, type, mount);\n-            if (uuid) {\n-                uuids.push(uuid);\n-            }\n-            else {\n-                this._urlNotFound(url, type, completeCallback);\n-                return;\n-            }\n-        }\n-        this._loadResUuids(uuids, progressCallback, completeCallback);\n-    }\n-\n-    /**\n-     * Load all assets in a folder inside the \"assets/resources\" folder of your project.<br>\n-     * <br>\n-     * Note: All asset URLs in Creator use forward slashes, URLs using backslashes will not work.\n-     *\n-     * @method loadResDir\n-     * @param {String} url - Url of the target folder.\n-     *                       The url is relative to the \"resources\" folder, extensions must be omitted.\n-     * @param {Function} [type] - Only asset of type will be loaded if this argument is supplied.\n-     * @param {Function} [progressCallback] - Callback invoked when progression change.\n-     * @param {Number} progressCallback.completedCount - The number of the items that are already completed.\n-     * @param {Number} progressCallback.totalCount - The total number of the items.\n-     * @param {Object} progressCallback.item - The latest item which flow out the pipeline.\n-     * @param {Function} [completeCallback] - A callback which is called when all assets have been loaded, or an error occurs.\n-     * @param {Error} completeCallback.error - If one of the asset failed, the complete callback is immediately called\n-     *                                         with the error. If all assets are loaded successfully, error will be null.\n-     * @param {Asset[]|Array} completeCallback.assets - An array of all loaded assets.\n-     *                                             If nothing to load, assets will be an empty array.\n-     * @param {String[]} completeCallback.urls - An array that lists all the URLs of loaded assets.\n-     *\n-     * @example\n-     *\n-     * // load the texture (resources/imgs/cocos.png) and the corresponding sprite frame\n-     * cc.loader.loadResDir('imgs/cocos', function (err, assets) {\n-     *     if (err) {\n-     *         cc.error(err);\n-     *         return;\n-     *     }\n-     *     var texture = assets[0];\n-     *     var spriteFrame = assets[1];\n-     * });\n-     *\n-     * // load all textures in \"resources/imgs/\"\n-     * cc.loader.loadResDir('imgs', cc.Texture2D, function (err, textures) {\n-     *     var texture1 = textures[0];\n-     *     var texture2 = textures[1];\n-     * });\n-     *\n-     * // load all JSONs in \"resources/data/\"\n-     * cc.loader.loadResDir('data', function (err, objects, urls) {\n-     *     var data = objects[0];\n-     *     var url = urls[0];\n-     * });\n-     * @typescript\n-     * loadResDir(url: string, type: typeof cc.Asset, progressCallback: (completedCount: number, totalCount: number, item: any) => void, completeCallback: ((error: Error, resource: any[], urls: string[]) => void)|null): void\n-     * loadResDir(url: string, type: typeof cc.Asset, completeCallback: (error: Error, resource: any[], urls: string[]) => void): void\n-     * loadResDir(url: string, type: typeof cc.Asset): void\n-     * loadResDir(url: string, progressCallback: (completedCount: number, totalCount: number, item: any) => void, completeCallback: ((error: Error, resource: any[], urls: string[]) => void)|null): void\n-     * loadResDir(url: string, completeCallback: (error: Error, resource: any[], urls: string[]) => void): void\n-     * loadResDir(url: string): void\n-     */\n-    loadResDir(url, type, mount, progressCallback, completeCallback) {\n-        if (arguments.length !== 5) {\n-            completeCallback = progressCallback;\n-            progressCallback = mount;\n-            mount = 'assets';\n-        }\n-\n-        if (!assetTables[mount]) return;\n-\n-        var args = this._parseLoadResArgs(type, progressCallback, completeCallback);\n-        type = args.type;\n-        progressCallback = args.onProgress;\n-        completeCallback = args.onComplete;\n-\n-        var urls = [];\n-        var uuids = assetTables[mount].getUuidArray(url, type, urls);\n-        this._loadResUuids(uuids, progressCallback, function (errors, assetRes, urlRes) {\n-            // The spriteFrame url in spriteAtlas will be removed after build project\n-            // To show users the exact structure in asset panel, we need to return the spriteFrame assets in spriteAtlas\n-            let assetResLength = assetRes.length;\n-            for (let i = 0; i < assetResLength; ++i) {\n-                if (assetRes[i] instanceof cc.SpriteAtlas) {\n-                    let spriteFrames = assetRes[i].getSpriteFrames();\n-                    for (let k in spriteFrames) {\n-                        let sf = spriteFrames[k];\n-                        assetRes.push(sf);\n-                        if (urlRes) {\n-                            urlRes.push(`${urlRes[i]}/${sf.name}`);\n-                        }\n-                    }\n-                }\n-            }\n-            completeCallback && completeCallback(errors, assetRes, urlRes);\n-        }, urls);\n-    }\n-\n-    /**\n-     * Get resource data by id. <br>\n-     * When you load resources with {{#crossLink \"loader/load:method\"}}{{/crossLink}} or {{#crossLink \"loader/loadRes:method\"}}{{/crossLink}},\n-     * the url will be the unique identity of the resource.\n-     * After loaded, you can acquire them by passing the url to this API.\n-     *\n-     * @method getRes\n-     * @param {String} url\n-     * @param {Function} [type] - Only asset of type will be returned if this argument is supplied.\n-     * @returns {*}\n-     */\n-    getRes(url, type) {\n-        var item = this._cache[url];\n-        if (!item) {\n-            var uuid = this._getResUuid(url, type, null, true);\n-            if (uuid) {\n-                var ref = this._getReferenceKey(uuid);\n-                item = this._cache[ref];\n-            }\n-            else {\n-                return null;\n-            }\n-        }\n-        if (item && item.alias) {\n-            item = item.alias;\n-        }\n-        return (item && item.complete) ? item.content : null;\n-    }\n-\n-    /**\n-     * Get total resources count in loader.\n-     * @returns {Number}\n-     */\n-    getResCount() {\n-        return Object.keys(this._cache).length;\n-    }\n-\n-    /**\n-     * !#en Get all resource dependencies of the requested asset in an array, including itself.\n-     * The owner parameter accept the following types: 1. The asset itself; 2. The resource url; 3. The asset's uuid.<br>\n-     * The returned array stores the dependencies with their uuids, after retrieve dependencies,\n-     * you can release them, access dependent assets by passing the uuid to {{#crossLink \"loader/getRes:method\"}}{{/crossLink}}, or other stuffs you want.<br>\n-     * For release all dependencies of an asset, please refer to {{#crossLink \"loader/release:method\"}}{{/crossLink}}\n-     * Here is some examples:\n-     * !#zh 获取一个指定资源的所有依赖资源，包含它自身，并保存在数组中返回。owner 参数接收以下几种类型：1. 资源 asset 对象；2. 资源目录下的 url；3. 资源的 uuid。<br>\n-     * 返回的数组将仅保存依赖资源的 uuid，获取这些 uuid 后，你可以从 loader 释放这些资源；通过 {{#crossLink \"loader/getRes:method\"}}{{/crossLink}} 获取某个资源或者进行其他你需要的操作。<br>\n-     * 想要释放一个资源及其依赖资源，可以参考 {{#crossLink \"loader/release:method\"}}{{/crossLink}}。下面是一些示例代码：\n-     *\n-     * @example\n-     * // Release all dependencies of a loaded prefab\n-     * var deps = cc.loader.getDependsRecursively(prefab);\n-     * cc.loader.release(deps);\n-     * // Retrieve all dependent textures\n-     * var deps = cc.loader.getDependsRecursively('prefabs/sample');\n-     * var textures = [];\n-     * for (var i = 0; i < deps.length; ++i) {\n-     *     var item = cc.loader.getRes(deps[i]);\n-     *     if (item instanceof cc.Texture2D) {\n-     *         textures.push(item);\n-     *     }\n-     * }\n-     *\n-     * @method getDependsRecursively\n-     * @param {Asset|RawAsset|String} owner - The owner asset or the resource url or the asset's uuid\n-     * @returns {Array}\n-     */\n-    getDependsRecursively(owner) {\n-        if (owner) {\n-            var key = this._getReferenceKey(owner);\n-            var assets = getDependsRecursively(key);\n-            assets.push(key);\n-            return assets;\n-        }\n-        else {\n-            return [];\n-        }\n-    }\n-\n-    /**\n-     * !#en\n-     * Release the content of an asset or an array of assets by uuid.\n-     * Start from v1.3, this method will not only remove the cache of the asset in loader, but also clean up its content.\n-     * For example, if you release a texture, the texture asset and its gl texture data will be freed up.\n-     * In complexe project, you can use this function with {{#crossLink \"loader/getDependsRecursively:method\"}}{{/crossLink}} to free up memory in critical circumstances.\n-     * Notice, this method may cause the texture to be unusable, if there are still other nodes use the same texture, they may turn to black and report gl errors.\n-     * If you only want to remove the cache of an asset, please use {{#crossLink \"pipeline/removeItem:method\"}}{{/crossLink}}\n-     * !#zh\n-     * 通过 id（通常是资源 url）来释放一个资源或者一个资源数组。\n-     * 从 v1.3 开始，这个方法不仅会从 loader 中删除资源的缓存引用，还会清理它的资源内容。\n-     * 比如说，当你释放一个 texture 资源，这个 texture 和它的 gl 贴图数据都会被释放。\n-     * 在复杂项目中，我们建议你结合 {{#crossLink \"loader/getDependsRecursively:method\"}}{{/crossLink}} 来使用，便于在设备内存告急的情况下更快地释放不再需要的资源的内存。\n-     * 注意，这个函数可能会导致资源贴图或资源所依赖的贴图不可用，如果场景中存在节点仍然依赖同样的贴图，它们可能会变黑并报 GL 错误。\n-     * 如果你只想删除一个资源的缓存引用，请使用 {{#crossLink \"pipeline/removeItem:method\"}}{{/crossLink}}\n-     *\n-     * @example\n-     * // Release a texture which is no longer need\n-     * cc.loader.release(texture);\n-     * // Release all dependencies of a loaded prefab\n-     * var deps = cc.loader.getDependsRecursively('prefabs/sample');\n-     * cc.loader.release(deps);\n-     * // If there is no instance of this prefab in the scene, the prefab and its dependencies like textures, sprite frames, etc, will be freed up.\n-     * // If you have some other nodes share a texture in this prefab, you can skip it in two ways:\n-     * // 1. Forbid auto release a texture before release\n-     * cc.loader.setAutoRelease(texture2d, false);\n-     * // 2. Remove it from the dependencies array\n-     * var deps = cc.loader.getDependsRecursively('prefabs/sample');\n-     * var index = deps.indexOf(texture2d._uuid);\n-     * if (index !== -1)\n-     *     deps.splice(index, 1);\n-     * cc.loader.release(deps);\n-     *\n-     * @method release\n-     * @param {Asset|RawAsset|String|Array} asset\n-     */\n-    release(asset) {\n-        if (Array.isArray(asset)) {\n-            for (let i = 0; i < asset.length; i++) {\n-                var key = asset[i];\n-                this.release(key);\n-            }\n-        }\n-        else if (asset) {\n-            var id = this._getReferenceKey(asset);\n-            var item = this.getItem(id);\n-            if (item) {\n-                var removed = this.removeItem(id);\n-                asset = item.content;\n-                if (asset instanceof cc.Asset) {\n-                    let nativeUrl = asset.nativeUrl;\n-                    if (nativeUrl) {\n-                        this.release(nativeUrl);  // uncache loading item of native asset\n-                    }\n-                    asset.destroy();\n-                }\n-                if (CC_DEBUG && removed) {\n-                    this._releasedAssetChecker_DEBUG.setReleased(item, id);\n-                }\n-            }\n-        }\n-    }\n-\n-    /**\n-     * !#en Release the asset by its object. Refer to {{#crossLink \"loader/release:method\"}}{{/crossLink}} for detailed informations.\n-     * !#zh 通过资源对象自身来释放资源。详细信息请参考 {{#crossLink \"loader/release:method\"}}{{/crossLink}}\n-     *\n-     * @method releaseAsset\n-     * @param {Asset} asset\n-     */\n-    releaseAsset(asset) {\n-        var uuid = asset._uuid;\n-        if (uuid) {\n-            this.release(uuid);\n-        }\n-    }\n-\n-    /**\n-     * !#en Release the asset loaded by {{#crossLink \"loader/loadRes:method\"}}{{/crossLink}}. Refer to {{#crossLink \"loader/release:method\"}}{{/crossLink}} for detailed informations.\n-     * !#zh 释放通过 {{#crossLink \"loader/loadRes:method\"}}{{/crossLink}} 加载的资源。详细信息请参考 {{#crossLink \"loader/release:method\"}}{{/crossLink}}\n-     *\n-     * @method releaseRes\n-     * @param {String} url\n-     * @param {Function} [type] - Only asset of type will be released if this argument is supplied.\n-     */\n-    releaseRes(url, type, mount) {\n-        var uuid = this._getResUuid(url, type, mount);\n-        if (uuid) {\n-            this.release(uuid);\n-        }\n-        else {\n-            cc.errorID(4914, url);\n-        }\n-    }\n-\n-    /**\n-     * !#en Release the all assets loaded by {{#crossLink \"loader/loadResDir:method\"}}{{/crossLink}}. Refer to {{#crossLink \"loader/release:method\"}}{{/crossLink}} for detailed informations.\n-     * !#zh 释放通过 {{#crossLink \"loader/loadResDir:method\"}}{{/crossLink}} 加载的资源。详细信息请参考 {{#crossLink \"loader/release:method\"}}{{/crossLink}}\n-     *\n-     * @method releaseResDir\n-     * @param {String} url\n-     * @param {Function} [type] - Only asset of type will be released if this argument is supplied.\n-     */\n-    releaseResDir(url, type, mount) {\n-        mount = mount || 'assets';\n-        if (!assetTables[mount]) return;\n-\n-        var uuids = assetTables[mount].getUuidArray(url, type);\n-        for (var i = 0; i < uuids.length; i++) {\n-            var uuid = uuids[i];\n-            this.release(uuid);\n-        }\n-    }\n-\n-    /**\n-     * !#en Resource all assets. Refer to {{#crossLink \"loader/release:method\"}}{{/crossLink}} for detailed informations.\n-     * !#zh 释放所有资源。详细信息请参考 {{#crossLink \"loader/release:method\"}}{{/crossLink}}\n-     *\n-     * @method releaseAll\n-     */\n-    releaseAll() {\n-        for (var id in this._cache) {\n-            this.release(id);\n-        }\n-    }\n-\n-    // AUTO RELEASE\n-\n-    // override\n-    removeItem(key) {\n-        var removed = Pipeline.prototype.removeItem.call(this, key);\n-        delete this._autoReleaseSetting[key];\n-        return removed;\n-    }\n-\n-    /**\n-     * !#en\n-     * Indicates whether to release the asset when loading a new scene.<br>\n-     * By default, when loading a new scene, all assets in the previous scene will be released or preserved\n-     * according to whether the previous scene checked the \"Auto Release Assets\" option.\n-     * On the other hand, assets dynamically loaded by using `cc.loader.loadRes` or `cc.loader.loadResDir`\n-     * will not be affected by that option, remain not released by default.<br>\n-     * Use this API to change the default behavior on a single asset, to force preserve or release specified asset when scene switching.<br>\n-     * <br>\n-     * See: {{#crossLink \"loader/setAutoReleaseRecursively:method\"}}cc.loader.setAutoReleaseRecursively{{/crossLink}}, {{#crossLink \"loader/isAutoRelease:method\"}}cc.loader.isAutoRelease{{/crossLink}}\n-     * !#zh\n-     * 设置当场景切换时是否自动释放资源。<br>\n-     * 默认情况下，当加载新场景时，旧场景的资源根据旧场景是否勾选“Auto Release Assets”，将会被释放或者保留。\n-     * 而使用 `cc.loader.loadRes` 或 `cc.loader.loadResDir` 动态加载的资源，则不受场景设置的影响，默认不自动释放。<br>\n-     * 使用这个 API 可以在单个资源上改变这个默认行为，强制在切换场景时保留或者释放指定资源。<br>\n-     * <br>\n-     * 参考：{{#crossLink \"loader/setAutoReleaseRecursively:method\"}}cc.loader.setAutoReleaseRecursively{{/crossLink}}，{{#crossLink \"loader/isAutoRelease:method\"}}cc.loader.isAutoRelease{{/crossLink}}\n-     *\n-     * @example\n-     * // auto release the texture event if \"Auto Release Assets\" disabled in current scene\n-     * cc.loader.setAutoRelease(texture2d, true);\n-     * // don't release the texture even if \"Auto Release Assets\" enabled in current scene\n-     * cc.loader.setAutoRelease(texture2d, false);\n-     * // first parameter can be url\n-     * cc.loader.setAutoRelease(audioUrl, false);\n-     *\n-     * @method setAutoRelease\n-     * @param {Asset|String} assetOrUrlOrUuid - asset object or the raw asset's url or uuid\n-     * @param {Boolean} autoRelease - indicates whether should release automatically\n-     */\n-    setAutoRelease(assetOrUrlOrUuid, autoRelease) {\n-        var key = this._getReferenceKey(assetOrUrlOrUuid);\n-        if (key) {\n-            this._autoReleaseSetting[key] = !!autoRelease;\n-        }\n-        else if (CC_DEV) {\n-            cc.warnID(4902);\n-        }\n-    }\n-\n-    /**\n-     * !#en\n-     * Indicates whether to release the asset and its referenced other assets when loading a new scene.<br>\n-     * By default, when loading a new scene, all assets in the previous scene will be released or preserved\n-     * according to whether the previous scene checked the \"Auto Release Assets\" option.\n-     * On the other hand, assets dynamically loaded by using `cc.loader.loadRes` or `cc.loader.loadResDir`\n-     * will not be affected by that option, remain not released by default.<br>\n-     * Use this API to change the default behavior on the specified asset and its recursively referenced assets, to force preserve or release specified asset when scene switching.<br>\n-     * <br>\n-     * See: {{#crossLink \"loader/setAutoRelease:method\"}}cc.loader.setAutoRelease{{/crossLink}}, {{#crossLink \"loader/isAutoRelease:method\"}}cc.loader.isAutoRelease{{/crossLink}}\n-     * !#zh\n-     * 设置当场景切换时是否自动释放资源及资源引用的其它资源。<br>\n-     * 默认情况下，当加载新场景时，旧场景的资源根据旧场景是否勾选“Auto Release Assets”，将会被释放或者保留。\n-     * 而使用 `cc.loader.loadRes` 或 `cc.loader.loadResDir` 动态加载的资源，则不受场景设置的影响，默认不自动释放。<br>\n-     * 使用这个 API 可以在指定资源及资源递归引用到的所有资源上改变这个默认行为，强制在切换场景时保留或者释放指定资源。<br>\n-     * <br>\n-     * 参考：{{#crossLink \"loader/setAutoRelease:method\"}}cc.loader.setAutoRelease{{/crossLink}}，{{#crossLink \"loader/isAutoRelease:method\"}}cc.loader.isAutoRelease{{/crossLink}}\n-     *\n-     * @example\n-     * // auto release the SpriteFrame and its Texture event if \"Auto Release Assets\" disabled in current scene\n-     * cc.loader.setAutoReleaseRecursively(spriteFrame, true);\n-     * // don't release the SpriteFrame and its Texture even if \"Auto Release Assets\" enabled in current scene\n-     * cc.loader.setAutoReleaseRecursively(spriteFrame, false);\n-     * // don't release the Prefab and all the referenced assets\n-     * cc.loader.setAutoReleaseRecursively(prefab, false);\n-     *\n-     * @method setAutoReleaseRecursively\n-     * @param {Asset|String} assetOrUrlOrUuid - asset object or the raw asset's url or uuid\n-     * @param {Boolean} autoRelease - indicates whether should release automatically\n-     */\n-    setAutoReleaseRecursively(assetOrUrlOrUuid, autoRelease) {\n-        autoRelease = !!autoRelease;\n-        var key = this._getReferenceKey(assetOrUrlOrUuid);\n-        if (key) {\n-            this._autoReleaseSetting[key] = autoRelease;\n-\n-            var depends = getDependsRecursively(key);\n-            for (var i = 0; i < depends.length; i++) {\n-                var depend = depends[i];\n-                this._autoReleaseSetting[depend] = autoRelease;\n-            }\n-        }\n-        else if (CC_DEV) {\n-            cc.warnID(4902);\n-        }\n-    }\n-\n-\n-    /**\n-     * !#en\n-     * Returns whether the asset is configured as auto released, despite how \"Auto Release Assets\" property is set on scene asset.<br>\n-     * <br>\n-     * See: {{#crossLink \"loader/setAutoRelease:method\"}}cc.loader.setAutoRelease{{/crossLink}}, {{#crossLink \"loader/setAutoReleaseRecursively:method\"}}cc.loader.setAutoReleaseRecursively{{/crossLink}}\n-     *\n-     * !#zh\n-     * 返回指定的资源是否有被设置为自动释放，不论场景的“Auto Release Assets”如何设置。<br>\n-     * <br>\n-     * 参考：{{#crossLink \"loader/setAutoRelease:method\"}}cc.loader.setAutoRelease{{/crossLink}}，{{#crossLink \"loader/setAutoReleaseRecursively:method\"}}cc.loader.setAutoReleaseRecursively{{/crossLink}}\n-     * @method isAutoRelease\n-     * @param {Asset|String} assetOrUrl - asset object or the raw asset's url\n-     * @returns {Boolean}\n-     */\n-    isAutoRelease(assetOrUrl) {\n-        var key = this._getReferenceKey(assetOrUrl);\n-        if (key) {\n-            return !!this._autoReleaseSetting[key];\n-        }\n-        return false;\n-    }\n-}\n-\n-/**\n- * Gets a new XMLHttpRequest instance.\n- * @method getXMLHttpRequest\n- * @returns {XMLHttpRequest}\n- */\n-CCLoader.prototype.getXMLHttpRequest = getXMLHttpRequest;\n-\n-let loader = cc.loader = new CCLoader();\n-\n-if (CC_EDITOR) {\n-    cc.loader.refreshUrl = function (uuid, oldUrl, newUrl) {\n-        var item = this._cache[uuid];\n-        if (item) {\n-            item.url = newUrl;\n-        }\n-\n-        item = this._cache[oldUrl];\n-        if (item) {\n-            item.id = newUrl;\n-            item.url = newUrl;\n-            this._cache[newUrl] = item;\n-            delete this._cache[oldUrl];\n-        }\n-    };\n-}\n-\n-export default loader;\n+/****************************************************************************\r\n+ Copyright (c) 2013-2016 Chukong Technologies Inc.\r\n+ Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.\r\n+\r\n+ http://www.cocos.com\r\n+\r\n+ Permission is hereby granted, free of charge, to any person obtaining a copy\r\n+ of this software and associated engine source code (the \"Software\"), a limited,\r\n+  worldwide, royalty-free, non-assignable, revocable and non-exclusive license\r\n+ to use Cocos Creator solely to develop games on your target platforms. You shall\r\n+  not use Cocos Creator software for developing other software or tools that's\r\n+  used for developing games. You are not granted to publish, distribute,\r\n+  sublicense, and/or sell copies of Cocos Creator.\r\n+\r\n+ The software or tools in this License Agreement are licensed, not sold.\r\n+ Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.\r\n+\r\n+ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n+ THE SOFTWARE.\r\n+ ****************************************************************************/\r\n+\r\n+import { createMap, getClassName, isChildClassOf } from '../core/utils/js';\r\n+import { callInNextTick } from '../core/utils/misc';\r\n+import AssetLoader from './asset-loader';\r\n+import AssetTable from './asset-table';\r\n+import { getDependsRecursively } from './auto-release-utils';\r\n+import Downloader from './downloader';\r\n+import Loader from './loader';\r\n+import LoadingItems from './loading-items';\r\n+import Pipeline from './pipeline';\r\n+import ReleasedAssetChecker from './released-asset-checker';\r\n+\r\n+const assetTables = Object.create(null);\r\n+assetTables.assets = new AssetTable();\r\n+assetTables.internal = new AssetTable();\r\n+\r\n+function getXMLHttpRequest () {\r\n+    return window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject('MSXML2.XMLHTTP');\r\n+}\r\n+\r\n+const _info = { url: null, raw: false };\r\n+\r\n+// Convert a resources by finding its real url with uuid, otherwise we will use the uuid or raw url as its url\r\n+// So we gurantee there will be url in result\r\n+function getResWithUrl (res) {\r\n+    let id;\r\n+    let result;\r\n+    let isUuid;\r\n+    if (typeof res === 'object') {\r\n+        result = res;\r\n+        if (res.url) {\r\n+            return result;\r\n+        }\r\n+        else {\r\n+            id = res.uuid;\r\n+        }\r\n+    }\r\n+    else {\r\n+        result = {};\r\n+        id = res;\r\n+    }\r\n+    isUuid = result.type ? result.type === 'uuid' : cc.AssetLibrary._uuidInSettings(id);\r\n+    cc.AssetLibrary._getAssetInfoInRuntime(id, _info);\r\n+    result.url = !isUuid ? id : _info.url;\r\n+    if (_info.url && result.type === 'uuid' && _info.raw) {\r\n+        result.type = null;\r\n+        result.isRawAsset = true;\r\n+    }\r\n+    else if (!isUuid) {\r\n+        result.isRawAsset = true;\r\n+    }\r\n+    return result;\r\n+}\r\n+\r\n+const _sharedResources: any = [];\r\n+const _sharedList: any = [];\r\n+\r\n+/**\r\n+ * Loader for resource loading process. It's a singleton object.\r\n+ * @class loader\r\n+ * @extends Pipeline\r\n+ * @static\r\n+ */\r\n+class CCLoader extends Pipeline {\r\n+\r\n+    /**\r\n+     * Gets a new XMLHttpRequest instance.\r\n+     * @method getXMLHttpRequest\r\n+     * @returns {XMLHttpRequest}\r\n+     */\r\n+    public getXMLHttpRequest;\r\n+\r\n+    public assetLoader: AssetLoader;\r\n+    public md5Pipe: null;\r\n+    public downloader: Downloader;\r\n+    public loader: Loader;\r\n+    public onProgress: null;\r\n+\r\n+    private _assetTables: any;\r\n+    private _autoReleaseSetting: any;\r\n+    private _releasedAssetChecker_DEBUG: any;\r\n+    private _ownerQueue: any;\r\n+\r\n+    constructor () {\r\n+\r\n+        const assetLoader = new AssetLoader();\r\n+        const downloader = new Downloader();\r\n+        // tslint:disable-next-line: no-shadowed-variable\r\n+        const loader = new Loader();\r\n+\r\n+        super([\r\n+            assetLoader,\r\n+            downloader,\r\n+            loader,\r\n+        ]);\r\n+\r\n+        this.getXMLHttpRequest =  getXMLHttpRequest;\r\n+\r\n+        /**\r\n+         * The asset loader in cc.loader's pipeline, it's by default the first pipe.\r\n+         * It's used to identify an asset's type, and determine how to download it.\r\n+         * @property assetLoader\r\n+         * @type {Object}\r\n+         */\r\n+        this.assetLoader = assetLoader;\r\n+\r\n+        /**\r\n+         * The md5 pipe in cc.loader's pipeline, it could be absent if the project isn't build with md5 option.\r\n+         * It's used to modify the url to the real downloadable url with md5 suffix.\r\n+         * @property md5Pipe\r\n+         * @type {Object}\r\n+         */\r\n+        this.md5Pipe = null;\r\n+\r\n+        /**\r\n+         * The downloader in cc.loader's pipeline, it's by default the second pipe.\r\n+         * It's used to download files with several handlers: pure text, image, script, audio, font, uuid.\r\n+         * You can add your own download function with addDownloadHandlers\r\n+         * @property downloader\r\n+         * @type {Object}\r\n+         */\r\n+        this.downloader = downloader;\r\n+\r\n+        /**\r\n+         * The loader in cc.loader's pipeline, it's by default the third pipe.\r\n+         * It's used to parse downloaded content with several handlers: JSON, image, plist, fnt, uuid.\r\n+         * You can add your own download function with addLoadHandlers\r\n+         * @property loader\r\n+         * @type {Object}\r\n+         */\r\n+        this.loader = loader;\r\n+\r\n+        this.onProgress = null;\r\n+\r\n+        this._assetTables = assetTables;\r\n+        // assets to release automatically\r\n+        this._autoReleaseSetting = createMap(true);\r\n+\r\n+        if (CC_DEBUG) {\r\n+            this._releasedAssetChecker_DEBUG = new ReleasedAssetChecker();\r\n+        }\r\n+    }\r\n+\r\n+    public init (director) {\r\n+        if (CC_DEBUG) {\r\n+            const self = this;\r\n+            director.on(cc.Director.EVENT_AFTER_UPDATE, () => {\r\n+                self._releasedAssetChecker_DEBUG.checkCouldRelease(self._cache);\r\n+            });\r\n+        }\r\n+    }\r\n+\r\n+    /**\r\n+     * Add custom supported types handler or modify existing type handler for download process.\r\n+     * @example\r\n+     *  cc.loader.addDownloadHandlers({\r\n+     *      // This will match all url with `.scene` extension or all url with `scene` type\r\n+     *      'scene' : function (url, callback) {}\r\n+     *  });\r\n+     * @method addDownloadHandlers\r\n+     * @param {Object} extMap Custom supported types with corresponded handler\r\n+     */\r\n+    public addDownloadHandlers (extMap: any) {\r\n+        this.downloader.addHandlers(extMap);\r\n+    }\r\n+\r\n+    /**\r\n+     * Add custom supported types handler or modify existing type handler for load process.\r\n+     * @example\r\n+     *  cc.loader.addLoadHandlers({\r\n+     *      // This will match all url with `.scene` extension or all url with `scene` type\r\n+     *      'scene' : function (url, callback) {}\r\n+     *  });\r\n+     * @method addLoadHandlers\r\n+     * @param {Object} extMap Custom supported types with corresponded handler\r\n+     */\r\n+    public  addLoadHandlers (extMap) {\r\n+        this.loader.addHandlers(extMap);\r\n+    }\r\n+\r\n+    // tslint:disable: max-line-length\r\n+\r\n+    /**\r\n+     * Load resources with a progression callback and a complete callback.\r\n+     * The progression callback is the same as Pipeline's {{#crossLink \"LoadingItems/onProgress:method\"}}onProgress{{/crossLink}}\r\n+     * The complete callback is almost the same as Pipeline's {{#crossLink \"LoadingItems/onComplete:method\"}}onComplete{{/crossLink}}\r\n+     * The only difference is when user pass a single url as resources, the complete callback will set its result directly as the second parameter.\r\n+     *\r\n+     * @example\r\n+     * cc.loader.load('a.png', function (err, tex) {\r\n+     *     cc.log('Result should be a texture: ' + (tex instanceof cc.Texture2D));\r\n+     * });\r\n+     *\r\n+     * cc.loader.load('http://example.com/a.png', function (err, tex) {\r\n+     *     cc.log('Should load a texture from external url: ' + (tex instanceof cc.Texture2D));\r\n+     * });\r\n+     *\r\n+     * cc.loader.load({url: 'http://example.com/getImageREST?file=a.png', type: 'png'}, function (err, tex) {\r\n+     *     cc.log('Should load a texture from RESTful API by specify the type: ' + (tex instanceof cc.Texture2D));\r\n+     * });\r\n+     *\r\n+     * cc.loader.load(['a.png', 'b.json'], function (errors, results) {\r\n+     *     if (errors) {\r\n+     *         for (var i = 0; i < errors.length; i++) {\r\n+     *             cc.log('Error url [' + errors[i] + ']: ' + results.getError(errors[i]));\r\n+     *         }\r\n+     *     }\r\n+     *     var aTex = results.getContent('a.png');\r\n+     *     var bJsonObj = results.getContent('b.json');\r\n+     * });\r\n+     *\r\n+     * @method load\r\n+     * @param {String|String[]|Object} resources - Url list in an array\r\n+     * @param {Function} [progressCallback] - Callback invoked when progression change\r\n+     * @param {Number} progressCallback.completedCount - The number of the items that are already completed\r\n+     * @param {Number} progressCallback.totalCount - The total number of the items\r\n+     * @param {Object} progressCallback.item - The latest item which flow out the pipeline\r\n+     * @param {Function} [completeCallback] - Callback invoked when all resources loaded\r\n+     * @typescript\r\n+     * load(resources: string|string[]|{uuid?: string, url?: string, type?: string}, completeCallback?: Function): void\r\n+     * load(resources: string|string[]|{uuid?: string, url?: string, type?: string}, progressCallback: (completedCount: number, totalCount: number, item: any) => void, completeCallback: Function|null): void\r\n+     */\r\n+    public load (resources, progressCallback, completeCallback) {\r\n+        if (CC_DEV && !resources) {\r\n+            return cc.error('[cc.loader.load] resources must be non-nil.');\r\n+        }\r\n+\r\n+        if (completeCallback === undefined) {\r\n+            completeCallback = progressCallback;\r\n+            progressCallback = this.onProgress || null;\r\n+        }\r\n+\r\n+        const self = this;\r\n+        let singleRes: Boolean = false;\r\n+        let res;\r\n+        if (!(resources instanceof Array)) {\r\n+            if (resources) {\r\n+                singleRes = true;\r\n+                resources = [resources];\r\n+            } else {\r\n+                resources = [];\r\n+            }\r\n+        }\r\n+\r\n+        _sharedResources.length = 0;\r\n+        // tslint:disable-next-line: prefer-for-of\r\n+        for (let i = 0; i < resources.length; ++i) {\r\n+            const resource = resources[i];\r\n+            // Backward compatibility\r\n+            if (resource && resource.id) {\r\n+                cc.warnID(4920, resource.id);\r\n+                if (!resource.uuid && !resource.url) {\r\n+                    resource.url = resource.id;\r\n+                }\r\n+            }\r\n+            res = getResWithUrl(resource);\r\n+            if (!res.url && !res.uuid) {\r\n+                continue;\r\n+            }\r\n+            const item = this._cache[res.url];\r\n+            _sharedResources.push(item || res);\r\n+        }\r\n+\r\n+        const queue = LoadingItems.create(this, progressCallback, (errors, items) => {\r\n+            callInNextTick(() => {\r\n+                if (completeCallback) {\r\n+                    if (singleRes) {\r\n+                        const id = res.url;\r\n+                        completeCallback.call(self, items.getError(id), items.getContent(id));\r\n+                    }\r\n+                    else {\r\n+                        completeCallback.call(self, errors, items);\r\n+                    }\r\n+                    completeCallback = null;\r\n+                }\r\n+\r\n+                items.destroy();\r\n+            });\r\n+        });\r\n+        LoadingItems.initQueueDeps(queue);\r\n+        queue.append(_sharedResources);\r\n+        _sharedResources.length = 0;\r\n+    }\r\n+\r\n+    public flowInDeps (owner, urlList, callback) {\r\n+        _sharedList.length = 0;\r\n+        for (const iterator of urlList) {\r\n+            const res = getResWithUrl(iterator);\r\n+            if (!res.url && !res.uuid) {\r\n+                continue;\r\n+            }\r\n+            const item = this._cache[res.url];\r\n+            if (item) {\r\n+                _sharedList.push(item);\r\n+            }\r\n+            else {\r\n+                _sharedList.push(res);\r\n+            }\r\n+        }\r\n+        // @ts-ignore\r\n+        const queue = LoadingItems.create(this, owner ? (completedCount, totalCount, item) => {\r\n+            if (this._ownerQueue && this._ownerQueue.onProgress) {\r\n+                this._ownerQueue._childOnProgress(item);\r\n+            }\r\n+        } : null, (errors, items) => {\r\n+            callback(errors, items);\r\n+            // Clear deps because it's already done\r\n+            // Each item will only flowInDeps once, so it's still safe here\r\n+            if (owner && owner.deps) {\r\n+                owner.deps.length = 0;\r\n+            }\r\n+            items.destroy();\r\n+        });\r\n+        if (owner) {\r\n+            const ownerQueue = LoadingItems.getQueue(owner);\r\n+            // Set the root ownerQueue, if no ownerQueue defined in ownerQueue, it's the root\r\n+            queue._ownerQueue = ownerQueue._ownerQueue || ownerQueue;\r\n+        }\r\n+        const accepted = queue.append(_sharedList, owner);\r\n+        _sharedList.length = 0;\r\n+        return accepted;\r\n+    }\r\n+\r\n+    /**\r\n+     * Load resources from the \"resources\" folder inside the \"assets\" folder of your project.<br>\r\n+     * <br>\r\n+     * Note: All asset URLs in Creator use forward slashes, URLs using backslashes will not work.\r\n+     *\r\n+     * @method loadRes\r\n+     * @param {String} url - Url of the target resource.\r\n+     *                       The url is relative to the \"resources\" folder, extensions must be omitted.\r\n+     * @param {Function} [type] - Only asset of type will be loaded if this argument is supplied.\r\n+     * @param {Function} [progressCallback] - Callback invoked when progression change.\r\n+     * @param {Number} progressCallback.completedCount - The number of the items that are already completed.\r\n+     * @param {Number} progressCallback.totalCount - The total number of the items.\r\n+     * @param {Object} progressCallback.item - The latest item which flow out the pipeline.\r\n+     * @param {Function} [completeCallback] - Callback invoked when the resource loaded.\r\n+     * @param {Error} completeCallback.error - The error info or null if loaded successfully.\r\n+     * @param {Object} completeCallback.resource - The loaded resource if it can be found otherwise returns null.\r\n+     *\r\n+     * @example\r\n+     *\r\n+     * // load the prefab (project/assets/resources/misc/character/cocos) from resources folder\r\n+     * cc.loader.loadRes('misc/character/cocos', function (err, prefab) {\r\n+     *     if (err) {\r\n+     *         cc.error(err.message || err);\r\n+     *         return;\r\n+     *     }\r\n+     *     cc.log('Result should be a prefab: ' + (prefab instanceof cc.Prefab));\r\n+     * });\r\n+     *\r\n+     * // load the sprite frame of (project/assets/resources/imgs/cocos.png) from resources folder\r\n+     * cc.loader.loadRes('imgs/cocos', cc.SpriteFrame, function (err, spriteFrame) {\r\n+     *     if (err) {\r\n+     *         cc.error(err.message || err);\r\n+     *         return;\r\n+     *     }\r\n+     *     cc.log('Result should be a sprite frame: ' + (spriteFrame instanceof cc.SpriteFrame));\r\n+     * });\r\n+     * @typescript\r\n+     * loadRes(url: string, type: typeof cc.Asset, progressCallback: (completedCount: number, totalCount: number, item: any) => void, completeCallback: ((error: Error, resource: any) => void)|null): void\r\n+     * loadRes(url: string, type: typeof cc.Asset, completeCallback: (error: Error, resource: any) => void): void\r\n+     * loadRes(url: string, type: typeof cc.Asset): void\r\n+     * loadRes(url: string, progressCallback: (completedCount: number, totalCount: number, item: any) => void, completeCallback: ((error: Error, resource: any) => void)|null): void\r\n+     * loadRes(url: string, completeCallback: (error: Error, resource: any) => void): void\r\n+     * loadRes(url: string): void\r\n+     */\r\n+    public loadRes (url, type, mount, progressCallback, completeCallback) {\r\n+        if (arguments.length !== 5) {\r\n+            completeCallback = progressCallback;\r\n+            progressCallback = mount;\r\n+            mount = 'assets';\r\n+        }\r\n+        const args = this._parseLoadResArgs(type, progressCallback, completeCallback);\r\n+        type = args.type;\r\n+        progressCallback = args.onProgress;\r\n+        completeCallback = args.onComplete;\r\n+        const self = this;\r\n+        const uuid = self._getResUuid(url, type, mount, true);\r\n+        if (uuid) {\r\n+            this.load(\r\n+                {\r\n+                    type: 'uuid',\r\n+                    uuid,\r\n+                },\r\n+                progressCallback,\r\n+                (err, asset) => {\r\n+                    if (asset) {\r\n+                        // should not release these assets, even if they are static referenced in the scene.\r\n+                        self.setAutoReleaseRecursively(uuid, false);\r\n+                    }\r\n+                    if (completeCallback) {\r\n+                        completeCallback(err, asset);\r\n+                    }\r\n+                });\r\n+        }\r\n+        else {\r\n+            self._urlNotFound(url, type, completeCallback);\r\n+        }\r\n+    }\r\n+\r\n+    /**\r\n+     * Load all assets in a folder inside the \"assets/resources\" folder of your project.<br>\r\n+     * <br>\r\n+     * Note: All asset URLs in Creator use forward slashes, URLs using backslashes will not work.\r\n+     *\r\n+     * @method loadResDir\r\n+     * @param {String} url - Url of the target folder.\r\n+     *                       The url is relative to the \"resources\" folder, extensions must be omitted.\r\n+     * @param {Function} [type] - Only asset of type will be loaded if this argument is supplied.\r\n+     * @param {Function} [progressCallback] - Callback invoked when progression change.\r\n+     * @param {Number} progressCallback.completedCount - The number of the items that are already completed.\r\n+     * @param {Number} progressCallback.totalCount - The total number of the items.\r\n+     * @param {Object} progressCallback.item - The latest item which flow out the pipeline.\r\n+     * @param {Function} [completeCallback] - A callback which is called when all assets have been loaded, or an error occurs.\r\n+     * @param {Error} completeCallback.error - If one of the asset failed, the complete callback is immediately called\r\n+     *                                         with the error. If all assets are loaded successfully, error will be null.\r\n+     * @param {Asset[]|Array} completeCallback.assets - An array of all loaded assets.\r\n+     *                                             If nothing to load, assets will be an empty array.\r\n+     * @param {String[]} completeCallback.urls - An array that lists all the URLs of loaded assets.\r\n+     *\r\n+     * @example\r\n+     *\r\n+     * // load the texture (resources/imgs/cocos.png) and the corresponding sprite frame\r\n+     * cc.loader.loadResDir('imgs/cocos', function (err, assets) {\r\n+     *     if (err) {\r\n+     *         cc.error(err);\r\n+     *         return;\r\n+     *     }\r\n+     *     var texture = assets[0];\r\n+     *     var spriteFrame = assets[1];\r\n+     * });\r\n+     *\r\n+     * // load all textures in \"resources/imgs/\"\r\n+     * cc.loader.loadResDir('imgs', cc.Texture2D, function (err, textures) {\r\n+     *     var texture1 = textures[0];\r\n+     *     var texture2 = textures[1];\r\n+     * });\r\n+     *\r\n+     * // load all JSONs in \"resources/data/\"\r\n+     * cc.loader.loadResDir('data', function (err, objects, urls) {\r\n+     *     var data = objects[0];\r\n+     *     var url = urls[0];\r\n+     * });\r\n+     * @typescript\r\n+     * loadResDir(url: string, type: typeof cc.Asset, progressCallback: (completedCount: number, totalCount: number, item: any) => void, completeCallback: ((error: Error, resource: any[], urls: string[]) => void)|null): void\r\n+     * loadResDir(url: string, type: typeof ","path":"cocos/load-pipeline/CCLoader.ts","position":1807,"original_position":1807,"commit_id":"f9848679b24279c84b1bc4bba8f2cad0ef96cc13","original_commit_id":"f9848679b24279c84b1bc4bba8f2cad0ef96cc13","user":{"login":"holycanvas","id":15109777,"node_id":"MDQ6VXNlcjE1MTA5Nzc3","avatar_url":"https://avatars2.githubusercontent.com/u/15109777?v=4","gravatar_id":"","url":"https://api.github.com/users/holycanvas","html_url":"https://github.com/holycanvas","followers_url":"https://api.github.com/users/holycanvas/followers","following_url":"https://api.github.com/users/holycanvas/following{/other_user}","gists_url":"https://api.github.com/users/holycanvas/gists{/gist_id}","starred_url":"https://api.github.com/users/holycanvas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/holycanvas/subscriptions","organizations_url":"https://api.github.com/users/holycanvas/orgs","repos_url":"https://api.github.com/users/holycanvas/repos","events_url":"https://api.github.com/users/holycanvas/events{/privacy}","received_events_url":"https://api.github.com/users/holycanvas/received_events","type":"User","site_admin":false},"body":"this._cache不是数组哦","created_at":"2019-05-21T10:05:29Z","updated_at":"2019-05-21T10:17:20Z","html_url":"https://github.com/cocos-creator/engine/pull/4403#discussion_r285948868","pull_request_url":"https://api.github.com/repos/cocos-creator/engine/pulls/4403","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/cocos-creator/engine/pulls/comments/285948868"},"html":{"href":"https://github.com/cocos-creator/engine/pull/4403#discussion_r285948868"},"pull_request":{"href":"https://api.github.com/repos/cocos-creator/engine/pulls/4403"}}},"pull_request":{"url":"https://api.github.com/repos/cocos-creator/engine/pulls/4403","id":277770800,"node_id":"MDExOlB1bGxSZXF1ZXN0Mjc3NzcwODAw","html_url":"https://github.com/cocos-creator/engine/pull/4403","diff_url":"https://github.com/cocos-creator/engine/pull/4403.diff","patch_url":"https://github.com/cocos-creator/engine/pull/4403.patch","issue_url":"https://api.github.com/repos/cocos-creator/engine/issues/4403","number":4403,"state":"closed","locked":false,"title":"Some core code modify to TS","user":{"login":"LinYunMo","id":42071583,"node_id":"MDQ6VXNlcjQyMDcxNTgz","avatar_url":"https://avatars3.githubusercontent.com/u/42071583?v=4","gravatar_id":"","url":"https://api.github.com/users/LinYunMo","html_url":"https://github.com/LinYunMo","followers_url":"https://api.github.com/users/LinYunMo/followers","following_url":"https://api.github.com/users/LinYunMo/following{/other_user}","gists_url":"https://api.github.com/users/LinYunMo/gists{/gist_id}","starred_url":"https://api.github.com/users/LinYunMo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/LinYunMo/subscriptions","organizations_url":"https://api.github.com/users/LinYunMo/orgs","repos_url":"https://api.github.com/users/LinYunMo/repos","events_url":"https://api.github.com/users/LinYunMo/events{/privacy}","received_events_url":"https://api.github.com/users/LinYunMo/received_events","type":"User","site_admin":false},"body":"部分核心代码改写为 TypeScript","created_at":"2019-05-10T13:30:12Z","updated_at":"2019-05-21T10:17:19Z","closed_at":"2019-05-11T14:52:52Z","merged_at":"2019-05-11T14:52:52Z","merge_commit_sha":"5e3eea8b560b29ce2aa4a5efb9ce94c656c7d4a7","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/cocos-creator/engine/pulls/4403/commits","review_comments_url":"https://api.github.com/repos/cocos-creator/engine/pulls/4403/comments","review_comment_url":"https://api.github.com/repos/cocos-creator/engine/pulls/comments{/number}","comments_url":"https://api.github.com/repos/cocos-creator/engine/issues/4403/comments","statuses_url":"https://api.github.com/repos/cocos-creator/engine/statuses/f9848679b24279c84b1bc4bba8f2cad0ef96cc13","head":{"label":"LinYunMo:3d","ref":"3d","sha":"f9848679b24279c84b1bc4bba8f2cad0ef96cc13","user":{"login":"LinYunMo","id":42071583,"node_id":"MDQ6VXNlcjQyMDcxNTgz","avatar_url":"https://avatars3.githubusercontent.com/u/42071583?v=4","gravatar_id":"","url":"https://api.github.com/users/LinYunMo","html_url":"https://github.com/LinYunMo","followers_url":"https://api.github.com/users/LinYunMo/followers","following_url":"https://api.github.com/users/LinYunMo/following{/other_user}","gists_url":"https://api.github.com/users/LinYunMo/gists{/gist_id}","starred_url":"https://api.github.com/users/LinYunMo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/LinYunMo/subscriptions","organizations_url":"https://api.github.com/users/LinYunMo/orgs","repos_url":"https://api.github.com/users/LinYunMo/repos","events_url":"https://api.github.com/users/LinYunMo/events{/privacy}","received_events_url":"https://api.github.com/users/LinYunMo/received_events","type":"User","site_admin":false},"repo":{"id":183899454,"node_id":"MDEwOlJlcG9zaXRvcnkxODM4OTk0NTQ=","name":"engine","full_name":"LinYunMo/engine","private":false,"owner":{"login":"LinYunMo","id":42071583,"node_id":"MDQ6VXNlcjQyMDcxNTgz","avatar_url":"https://avatars3.githubusercontent.com/u/42071583?v=4","gravatar_id":"","url":"https://api.github.com/users/LinYunMo","html_url":"https://github.com/LinYunMo","followers_url":"https://api.github.com/users/LinYunMo/followers","following_url":"https://api.github.com/users/LinYunMo/following{/other_user}","gists_url":"https://api.github.com/users/LinYunMo/gists{/gist_id}","starred_url":"https://api.github.com/users/LinYunMo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/LinYunMo/subscriptions","organizations_url":"https://api.github.com/users/LinYunMo/orgs","repos_url":"https://api.github.com/users/LinYunMo/repos","events_url":"https://api.github.com/users/LinYunMo/events{/privacy}","received_events_url":"https://api.github.com/users/LinYunMo/received_events","type":"User","site_admin":false},"html_url":"https://github.com/LinYunMo/engine","description":"Cocos Creator is a complete package of game development tools and workflow, including a game engine, resource management, scene editing, game preview, debug and publish one project to multiple platforms.","fork":true,"url":"https://api.github.com/repos/LinYunMo/engine","forks_url":"https://api.github.com/repos/LinYunMo/engine/forks","keys_url":"https://api.github.com/repos/LinYunMo/engine/keys{/key_id}","collaborators_url":"https://api.github.com/repos/LinYunMo/engine/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/LinYunMo/engine/teams","hooks_url":"https://api.github.com/repos/LinYunMo/engine/hooks","issue_events_url":"https://api.github.com/repos/LinYunMo/engine/issues/events{/number}","events_url":"https://api.github.com/repos/LinYunMo/engine/events","assignees_url":"https://api.github.com/repos/LinYunMo/engine/assignees{/user}","branches_url":"https://api.github.com/repos/LinYunMo/engine/branches{/branch}","tags_url":"https://api.github.com/repos/LinYunMo/engine/tags","blobs_url":"https://api.github.com/repos/LinYunMo/engine/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/LinYunMo/engine/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/LinYunMo/engine/git/refs{/sha}","trees_url":"https://api.github.com/repos/LinYunMo/engine/git/trees{/sha}","statuses_url":"https://api.github.com/repos/LinYunMo/engine/statuses/{sha}","languages_url":"https://api.github.com/repos/LinYunMo/engine/languages","stargazers_url":"https://api.github.com/repos/LinYunMo/engine/stargazers","contributors_url":"https://api.github.com/repos/LinYunMo/engine/contributors","subscribers_url":"https://api.github.com/repos/LinYunMo/engine/subscribers","subscription_url":"https://api.github.com/repos/LinYunMo/engine/subscription","commits_url":"https://api.github.com/repos/LinYunMo/engine/commits{/sha}","git_commits_url":"https://api.github.com/repos/LinYunMo/engine/git/commits{/sha}","comments_url":"https://api.github.com/repos/LinYunMo/engine/comments{/number}","issue_comment_url":"https://api.github.com/repos/LinYunMo/engine/issues/comments{/number}","contents_url":"https://api.github.com/repos/LinYunMo/engine/contents/{+path}","compare_url":"https://api.github.com/repos/LinYunMo/engine/compare/{base}...{head}","merges_url":"https://api.github.com/repos/LinYunMo/engine/merges","archive_url":"https://api.github.com/repos/LinYunMo/engine/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/LinYunMo/engine/downloads","issues_url":"https://api.github.com/repos/LinYunMo/engine/issues{/number}","pulls_url":"https://api.github.com/repos/LinYunMo/engine/pulls{/number}","milestones_url":"https://api.github.com/repos/LinYunMo/engine/milestones{/number}","notifications_url":"https://api.github.com/repos/LinYunMo/engine/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/LinYunMo/engine/labels{/name}","releases_url":"https://api.github.com/repos/LinYunMo/engine/releases{/id}","deployments_url":"https://api.github.com/repos/LinYunMo/engine/deployments","created_at":"2019-04-28T11:29:13Z","updated_at":"2019-04-28T11:29:18Z","pushed_at":"2019-05-21T08:13:33Z","git_url":"git://github.com/LinYunMo/engine.git","ssh_url":"git@github.com:LinYunMo/engine.git","clone_url":"https://github.com/LinYunMo/engine.git","svn_url":"https://github.com/LinYunMo/engine","homepage":"http://www.cocos2d-x.org/creator","size":46332,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":0,"license":null,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"cocos-creator:3d","ref":"3d","sha":"c37bec5b9cd6a28f2ae1b090ea70290db9b2f893","user":{"login":"cocos-creator","id":6937061,"node_id":"MDEyOk9yZ2FuaXphdGlvbjY5MzcwNjE=","avatar_url":"https://avatars3.githubusercontent.com/u/6937061?v=4","gravatar_id":"","url":"https://api.github.com/users/cocos-creator","html_url":"https://github.com/cocos-creator","followers_url":"https://api.github.com/users/cocos-creator/followers","following_url":"https://api.github.com/users/cocos-creator/following{/other_user}","gists_url":"https://api.github.com/users/cocos-creator/gists{/gist_id}","starred_url":"https://api.github.com/users/cocos-creator/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cocos-creator/subscriptions","organizations_url":"https://api.github.com/users/cocos-creator/orgs","repos_url":"https://api.github.com/users/cocos-creator/repos","events_url":"https://api.github.com/users/cocos-creator/events{/privacy}","received_events_url":"https://api.github.com/users/cocos-creator/received_events","type":"Organization","site_admin":false},"repo":{"id":47440536,"node_id":"MDEwOlJlcG9zaXRvcnk0NzQ0MDUzNg==","name":"engine","full_name":"cocos-creator/engine","private":false,"owner":{"login":"cocos-creator","id":6937061,"node_id":"MDEyOk9yZ2FuaXphdGlvbjY5MzcwNjE=","avatar_url":"https://avatars3.githubusercontent.com/u/6937061?v=4","gravatar_id":"","url":"https://api.github.com/users/cocos-creator","html_url":"https://github.com/cocos-creator","followers_url":"https://api.github.com/users/cocos-creator/followers","following_url":"https://api.github.com/users/cocos-creator/following{/other_user}","gists_url":"https://api.github.com/users/cocos-creator/gists{/gist_id}","starred_url":"https://api.github.com/users/cocos-creator/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cocos-creator/subscriptions","organizations_url":"https://api.github.com/users/cocos-creator/orgs","repos_url":"https://api.github.com/users/cocos-creator/repos","events_url":"https://api.github.com/users/cocos-creator/events{/privacy}","received_events_url":"https://api.github.com/users/cocos-creator/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/cocos-creator/engine","description":"Cocos Creator is a complete package of game development tools and workflow, including a game engine, resource management, scene editing, game preview, debug and publish one project to multiple platforms.","fork":false,"url":"https://api.github.com/repos/cocos-creator/engine","forks_url":"https://api.github.com/repos/cocos-creator/engine/forks","keys_url":"https://api.github.com/repos/cocos-creator/engine/keys{/key_id}","collaborators_url":"https://api.github.com/repos/cocos-creator/engine/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/cocos-creator/engine/teams","hooks_url":"https://api.github.com/repos/cocos-creator/engine/hooks","issue_events_url":"https://api.github.com/repos/cocos-creator/engine/issues/events{/number}","events_url":"https://api.github.com/repos/cocos-creator/engine/events","assignees_url":"https://api.github.com/repos/cocos-creator/engine/assignees{/user}","branches_url":"https://api.github.com/repos/cocos-creator/engine/branches{/branch}","tags_url":"https://api.github.com/repos/cocos-creator/engine/tags","blobs_url":"https://api.github.com/repos/cocos-creator/engine/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/cocos-creator/engine/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/cocos-creator/engine/git/refs{/sha}","trees_url":"https://api.github.com/repos/cocos-creator/engine/git/trees{/sha}","statuses_url":"https://api.github.com/repos/cocos-creator/engine/statuses/{sha}","languages_url":"https://api.github.com/repos/cocos-creator/engine/languages","stargazers_url":"https://api.github.com/repos/cocos-creator/engine/stargazers","contributors_url":"https://api.github.com/repos/cocos-creator/engine/contributors","subscribers_url":"https://api.github.com/repos/cocos-creator/engine/subscribers","subscription_url":"https://api.github.com/repos/cocos-creator/engine/subscription","commits_url":"https://api.github.com/repos/cocos-creator/engine/commits{/sha}","git_commits_url":"https://api.github.com/repos/cocos-creator/engine/git/commits{/sha}","comments_url":"https://api.github.com/repos/cocos-creator/engine/comments{/number}","issue_comment_url":"https://api.github.com/repos/cocos-creator/engine/issues/comments{/number}","contents_url":"https://api.github.com/repos/cocos-creator/engine/contents/{+path}","compare_url":"https://api.github.com/repos/cocos-creator/engine/compare/{base}...{head}","merges_url":"https://api.github.com/repos/cocos-creator/engine/merges","archive_url":"https://api.github.com/repos/cocos-creator/engine/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/cocos-creator/engine/downloads","issues_url":"https://api.github.com/repos/cocos-creator/engine/issues{/number}","pulls_url":"https://api.github.com/repos/cocos-creator/engine/pulls{/number}","milestones_url":"https://api.github.com/repos/cocos-creator/engine/milestones{/number}","notifications_url":"https://api.github.com/repos/cocos-creator/engine/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/cocos-creator/engine/labels{/name}","releases_url":"https://api.github.com/repos/cocos-creator/engine/releases{/id}","deployments_url":"https://api.github.com/repos/cocos-creator/engine/deployments","created_at":"2015-12-05T03:28:59Z","updated_at":"2019-05-20T09:49:24Z","pushed_at":"2019-05-21T09:36:45Z","git_url":"git://github.com/cocos-creator/engine.git","ssh_url":"git@github.com:cocos-creator/engine.git","clone_url":"https://github.com/cocos-creator/engine.git","svn_url":"https://github.com/cocos-creator/engine","homepage":"http://www.cocos2d-x.org/creator","size":46486,"stargazers_count":1092,"watchers_count":1092,"language":"JavaScript","has_issues":true,"has_projects":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":586,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":194,"license":null,"forks":586,"open_issues":194,"watchers":1092,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/cocos-creator/engine/pulls/4403"},"html":{"href":"https://github.com/cocos-creator/engine/pull/4403"},"issue":{"href":"https://api.github.com/repos/cocos-creator/engine/issues/4403"},"comments":{"href":"https://api.github.com/repos/cocos-creator/engine/issues/4403/comments"},"review_comments":{"href":"https://api.github.com/repos/cocos-creator/engine/pulls/4403/comments"},"review_comment":{"href":"https://api.github.com/repos/cocos-creator/engine/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/cocos-creator/engine/pulls/4403/commits"},"statuses":{"href":"https://api.github.com/repos/cocos-creator/engine/statuses/f9848679b24279c84b1bc4bba8f2cad0ef96cc13"}},"author_association":"NONE"}}
{"actor":{"display_login":"holycanvas"}}