mirror of
https://github.com/smallmain/cocos-enhance-kit.git
synced 2025-11-24 03:27:35 +00:00
初始化
This commit is contained in:
33
engine/gulp/browserify_prelude.js
Normal file
33
engine/gulp/browserify_prelude.js
Normal file
@@ -0,0 +1,33 @@
|
||||
|
||||
// Based on https://github.com/substack/browser-pack/blob/master/prelude.js
|
||||
|
||||
// modules are defined as an array
|
||||
// [ module function, map of requireuires ]
|
||||
//
|
||||
// map of requireuires is short require name -> numeric require
|
||||
//
|
||||
// anything defined in a previous bundle is accessed via the
|
||||
// orig method which is the requireuire for previous bundles
|
||||
|
||||
(function outer (modules, cache, entry) {
|
||||
function newRequire(name, jumped){
|
||||
var module = cache[name];
|
||||
if(!module) {
|
||||
var moduleData = modules[name];
|
||||
if(!moduleData) {
|
||||
// this module is excluded from engine
|
||||
return undefined;
|
||||
}
|
||||
var exports = {};
|
||||
module = cache[name] = {exports: exports};
|
||||
moduleData[0](function(x){
|
||||
return newRequire(moduleData[1][x] || x);
|
||||
},module,exports);
|
||||
}
|
||||
return module.exports;
|
||||
}
|
||||
for(var i=0;i<entry.length;i++) newRequire(entry[i]);
|
||||
|
||||
// Override the current require with this new one
|
||||
return newRequire;
|
||||
})
|
||||
29
engine/gulp/tasks/buildDebugInfos.js
Normal file
29
engine/gulp/tasks/buildDebugInfos.js
Normal file
@@ -0,0 +1,29 @@
|
||||
const Fs = require('fs');
|
||||
|
||||
module.exports = function buildDebugInfos () {
|
||||
let readContent = Fs.readFileSync('EngineErrorMap.md', 'utf-8');
|
||||
let titleRegExp = /### \d+/g;
|
||||
let debugInfos = {};
|
||||
|
||||
let result1 = titleRegExp.exec(readContent);
|
||||
while (result1) {
|
||||
let result2 = titleRegExp.exec(readContent);
|
||||
let errInfoHead = result1.index + result1[0].length;
|
||||
let errInfoTail = result2? result2.index: readContent.length;
|
||||
|
||||
let errCode = /\d+/.exec(result1[0])[0];
|
||||
let errInfo = readContent.slice(errInfoHead, errInfoTail);
|
||||
errInfo = errInfo.replace(/```/g, ' ');
|
||||
errInfo = errInfo.trim();
|
||||
errInfo = errInfo.replace(/\r\n/g, '\n');
|
||||
|
||||
if (!errInfo.includes('<!-- DEPRECATED -->')) {
|
||||
debugInfos[`${errCode}`] = errInfo;
|
||||
}
|
||||
|
||||
result1 = result2;
|
||||
}
|
||||
|
||||
let writeContent = JSON.stringify(debugInfos, null, 4);
|
||||
Fs.writeFileSync('DebugInfos.json', writeContent);
|
||||
};
|
||||
544
engine/gulp/tasks/engine.js
Normal file
544
engine/gulp/tasks/engine.js
Normal file
@@ -0,0 +1,544 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
'use strict';
|
||||
|
||||
const Utils = require('../util/utils');
|
||||
const createBundler = require('../util/create-bundler');
|
||||
const Path = require('path');
|
||||
const Fs = require('fs-extra');
|
||||
|
||||
const Source = require('vinyl-source-stream');
|
||||
const Gulp = require('gulp');
|
||||
const Buffer = require('vinyl-buffer');
|
||||
const Sourcemaps = require('gulp-sourcemaps');
|
||||
const EventStream = require('event-stream');
|
||||
const Chalk = require('chalk');
|
||||
const HandleErrors = require('../util/handleErrors');
|
||||
const Optimizejs = require('gulp-optimize-js');
|
||||
|
||||
let buildSkipModules = [
|
||||
'../../cocos2d/core/platform/deserialize-editor.js',
|
||||
];
|
||||
|
||||
let physicsSkipModules = [
|
||||
'../../cocos2d/core/3d/physics/exports/physics-builtin.ts',
|
||||
'../../cocos2d/core/3d/physics/exports/physics-cannon.ts',
|
||||
'../../cocos2d/core/3d/physics/exports/physics-framework.ts',
|
||||
'../../cocos2d/core/3d/physics/framework/assets/physics-material.ts',
|
||||
'../../external/cannon/cannon.js',
|
||||
];
|
||||
|
||||
var jsbSkipModules = [
|
||||
// modules need to skip in jsb
|
||||
'../../extensions/spine/skeleton-cache.js',
|
||||
'../../extensions/spine/vertex-effect-delegate.js',
|
||||
'../../extensions/spine/lib/spine.js',
|
||||
'../../extensions/dragonbones/lib/dragonBones.js',
|
||||
'../../extensions/dragonbones/ArmatureCache.js',
|
||||
'../../extensions/dragonbones/CCArmatureDisplay.js',
|
||||
'../../extensions/dragonbones/CCFactory.js',
|
||||
'../../extensions/dragonbones/CCSlot.js',
|
||||
'../../extensions/dragonbones/CCTextureData.js',
|
||||
|
||||
// gfx
|
||||
'../../cocos2d/renderer/gfx/device.js',
|
||||
'../../cocos2d/renderer/gfx/enums.js',
|
||||
'../../cocos2d/renderer/gfx/frame-buffer.js',
|
||||
'../../cocos2d/renderer/gfx/index-buffer.js',
|
||||
'../../cocos2d/renderer/gfx/misc.js',
|
||||
'../../cocos2d/renderer/gfx/program.js',
|
||||
'../../cocos2d/renderer/gfx/render-buffer.js',
|
||||
'../../cocos2d/renderer/gfx/state.js',
|
||||
'../../cocos2d/renderer/gfx/texture-2d.js',
|
||||
'../../cocos2d/renderer/gfx/texture-cube.js',
|
||||
'../../cocos2d/renderer/gfx/texture.js',
|
||||
'../../cocos2d/renderer/gfx/vertex-buffer.js',
|
||||
'../../cocos2d/renderer/gfx/vertex-format.js',
|
||||
|
||||
// renderer
|
||||
'../../cocos2d/renderer/core/base-renderer.js',
|
||||
'../../cocos2d/renderer/core/program-lib.js',
|
||||
'../../cocos2d/renderer/core/view.js',
|
||||
'../../cocos2d/renderer/renderers/forward-renderer.js',
|
||||
'../../cocos2d/renderer/scene/camera.js',
|
||||
'../../cocos2d/renderer/scene/light.js',
|
||||
'../../cocos2d/renderer/scene/scene.js',
|
||||
|
||||
// buffer
|
||||
'../../cocos2d/core/renderer/webgl/model-batcher.js',
|
||||
'../../cocos2d/core/renderer/webgl/spine-buffer.js',
|
||||
];
|
||||
var jsbAliasify = {
|
||||
replacements: {
|
||||
// '(.*)render-engine(.js)?': require.resolve('../../cocos2d/core/renderer/render-engine.jsb')
|
||||
},
|
||||
verbose: false
|
||||
};
|
||||
|
||||
const WEBVIEW_REGEXP = /[Ww]eb[Vv]iew/;
|
||||
function excludedWebView (excludes) {
|
||||
return excludes ? excludes.some(item => /.*CCWebView(\.js)?/.test(item)) : false;
|
||||
}
|
||||
|
||||
exports.buildDebugInfos = require('./buildDebugInfos');
|
||||
|
||||
exports.buildCocosJs = function (sourceFile, outputFile, excludes, opt_macroFlags, callback, createMap) {
|
||||
if (typeof opt_macroFlags === 'function') {
|
||||
callback = opt_macroFlags;
|
||||
opt_macroFlags = null;
|
||||
}
|
||||
|
||||
var opts = {
|
||||
sourcemaps: createMap !== false
|
||||
};
|
||||
var outDir = Path.dirname(outputFile);
|
||||
var outFile = Path.basename(outputFile);
|
||||
var bundler = createBundler(sourceFile, opts);
|
||||
|
||||
buildSkipModules.concat(physicsSkipModules).forEach(function (file) {
|
||||
bundler.exclude(require.resolve(file));
|
||||
});
|
||||
excludes && excludes.forEach(function (file) {
|
||||
bundler.exclude(file);
|
||||
});
|
||||
|
||||
bundler = bundler.bundle();
|
||||
bundler = bundler.pipe(Source(outFile));
|
||||
bundler = bundler.pipe(Buffer());
|
||||
|
||||
if (createMap) {
|
||||
bundler = bundler.pipe(Sourcemaps.init({loadMaps: true}));
|
||||
}
|
||||
|
||||
bundler = bundler.pipe(Utils.uglify('build', Object.assign({ debug: true }, opt_macroFlags)));
|
||||
bundler = bundler.pipe(Optimizejs({
|
||||
sourceMap: false
|
||||
}));
|
||||
|
||||
if (createMap) {
|
||||
bundler = bundler.pipe(Sourcemaps.write('./', {
|
||||
sourceRoot: './',
|
||||
includeContent: true,
|
||||
addComment: true
|
||||
}));
|
||||
}
|
||||
|
||||
bundler = bundler.pipe(Gulp.dest(outDir));
|
||||
return bundler.on('end', callback);
|
||||
};
|
||||
|
||||
exports.buildCocosJsMin = function (sourceFile, outputFile, excludes, opt_macroFlags, callback, createMap) {
|
||||
if (typeof opt_macroFlags === 'function') {
|
||||
callback = opt_macroFlags;
|
||||
opt_macroFlags = null;
|
||||
}
|
||||
|
||||
var opts = {
|
||||
sourcemaps: createMap !== false
|
||||
};
|
||||
var outDir = Path.dirname(outputFile);
|
||||
var outFile = Path.basename(outputFile);
|
||||
var bundler = createBundler(sourceFile, opts);
|
||||
|
||||
buildSkipModules.concat(physicsSkipModules).forEach(function (file) {
|
||||
bundler.exclude(require.resolve(file));
|
||||
});
|
||||
excludes && excludes.forEach(function (file) {
|
||||
bundler.exclude(file);
|
||||
});
|
||||
|
||||
bundler.exclude(Path.resolve(__dirname, '../../DebugInfos.json'));
|
||||
|
||||
var Size = null;
|
||||
try {
|
||||
Size = require('gulp-size');
|
||||
} catch (error) {
|
||||
Size = null;
|
||||
}
|
||||
|
||||
if (Size) {
|
||||
var rawSize = Size({ gzip: false, pretty: false, showTotal: false, showFiles: false });
|
||||
var zippedSize = Size({ gzip: true, pretty: false, showTotal: false, showFiles: false });
|
||||
}
|
||||
|
||||
bundler = bundler.bundle();
|
||||
bundler = bundler.pipe(Source(outFile));
|
||||
bundler = bundler.pipe(Buffer());
|
||||
if (createMap) {
|
||||
console.error('Can not use sourcemap with optimize-js');
|
||||
bundler = bundler.pipe(Sourcemaps.init({loadMaps: true}));
|
||||
}
|
||||
bundler = bundler.pipe(Utils.uglify('build', opt_macroFlags));
|
||||
bundler = bundler.pipe(Optimizejs({
|
||||
sourceMap: false
|
||||
}));
|
||||
|
||||
if (Size) {
|
||||
bundler = bundler.pipe(rawSize);
|
||||
bundler = bundler.pipe(zippedSize);
|
||||
bundler = bundler.pipe(EventStream.through(null, function () {
|
||||
var raw = rawSize.size;
|
||||
var zipped = zippedSize.size;
|
||||
var percent = ((zipped / raw) * 100).toFixed(2);
|
||||
console.log(`Size of ${outputFile}: minimized: ${Chalk.cyan(raw)}B zipped: ${Chalk.cyan(zipped)}B, compression ratio: ${percent}%`);
|
||||
this.emit('end');
|
||||
}));
|
||||
}
|
||||
if (createMap) {
|
||||
bundler = bundler.pipe(Sourcemaps.write('./', {
|
||||
sourceRoot: './',
|
||||
includeContent: true,
|
||||
addComment: true
|
||||
}));
|
||||
}
|
||||
bundler = bundler.pipe(Gulp.dest(outDir));
|
||||
return bundler.on('end', callback);
|
||||
};
|
||||
|
||||
exports.buildPreview = function (sourceFile, outputFile, callback, devMode) {
|
||||
var cacheDir = devMode && Path.resolve(Path.dirname(outputFile), '.cache/preview-compile-cache');
|
||||
var outFile = Path.basename(outputFile);
|
||||
var outDir = Path.dirname(outputFile);
|
||||
|
||||
var bundler = createBundler(sourceFile, {
|
||||
cacheDir: cacheDir,
|
||||
sourcemaps: !devMode
|
||||
});
|
||||
// NOTE: no need to exclude physics module for cocos2d-js-preview.js
|
||||
var bundler = bundler
|
||||
.bundle()
|
||||
.on('error', HandleErrors.handler)
|
||||
.pipe(HandleErrors())
|
||||
.pipe(Source(outFile))
|
||||
.pipe(Buffer());
|
||||
if (!devMode) {
|
||||
bundler = bundler
|
||||
.pipe(Sourcemaps.init({loadMaps: true}))
|
||||
.pipe(Utils.uglify('preview', {physics_cannon: true}))
|
||||
.pipe(Optimizejs({
|
||||
sourceMap: false
|
||||
}))
|
||||
.pipe(Sourcemaps.write('./', {
|
||||
sourceRoot: '../',
|
||||
includeContent: false,
|
||||
addComment: true
|
||||
}));
|
||||
}
|
||||
bundler
|
||||
.pipe(Gulp.dest(outDir))
|
||||
.on('end', callback);
|
||||
};
|
||||
|
||||
exports.buildJsbPreview = function (sourceFile, outputFile, excludes, callback) {
|
||||
var FixJavaScriptCore = require('../util/fix-jsb-javascriptcore');
|
||||
|
||||
var outFile = Path.basename(outputFile);
|
||||
var outDir = Path.dirname(outputFile);
|
||||
|
||||
excludes = excludes.concat(jsbSkipModules);
|
||||
|
||||
var bundler = createBundler(sourceFile);
|
||||
// NOTE: no need to exclude physics module for cocos2d-jsb-preview.js
|
||||
excludes.forEach(function (module) {
|
||||
bundler.exclude(require.resolve(module));
|
||||
});
|
||||
bundler.bundle()
|
||||
.on('error', HandleErrors.handler)
|
||||
.pipe(HandleErrors())
|
||||
.pipe(Source(outFile))
|
||||
.pipe(Buffer())
|
||||
.pipe(FixJavaScriptCore())
|
||||
.pipe(Utils.uglify('preview', { jsb: true, nativeRenderer: true, physics_cannon: true}))
|
||||
.pipe(Optimizejs({
|
||||
sourceMap: false
|
||||
}))
|
||||
.pipe(Gulp.dest(outDir))
|
||||
.on('end', callback);
|
||||
};
|
||||
|
||||
exports.buildJsb = function (sourceFile, outputFile, excludes, opt_macroFlags, callback, createMap) {
|
||||
if (typeof opt_macroFlags === 'function') {
|
||||
callback = opt_macroFlags;
|
||||
opt_macroFlags = null;
|
||||
}
|
||||
|
||||
var opts = {
|
||||
sourcemaps: createMap !== false
|
||||
};
|
||||
|
||||
let flags = Object.assign({ jsb: true, debug: true }, opt_macroFlags);
|
||||
let macro = Utils.getMacros('build', flags);
|
||||
let nativeRenderer = macro["CC_NATIVERENDERER"];
|
||||
let needHandleWebview = excludedWebView(excludes);
|
||||
|
||||
if (opt_macroFlags && nativeRenderer) {
|
||||
opts.aliasifyConfig = jsbAliasify;
|
||||
}
|
||||
if (needHandleWebview) {
|
||||
opts.aliasifyConfig = opts.aliasifyConfig || jsbAliasify;
|
||||
// this will replace require call with an empty object
|
||||
opts.aliasifyConfig.replacements['.*CCWebView(\.js)?'] = false;
|
||||
}
|
||||
|
||||
var FixJavaScriptCore = require('../util/fix-jsb-javascriptcore');
|
||||
|
||||
var outFile = Path.basename(outputFile);
|
||||
var outDir = Path.dirname(outputFile);
|
||||
|
||||
var bundler = createBundler(sourceFile, opts);
|
||||
buildSkipModules.concat(physicsSkipModules).forEach(function (file) {
|
||||
bundler.exclude(require.resolve(file));
|
||||
});
|
||||
if (nativeRenderer) {
|
||||
excludes = excludes.concat(jsbSkipModules);
|
||||
}
|
||||
excludes.forEach(function (module) {
|
||||
bundler.exclude(require.resolve(module));
|
||||
});
|
||||
bundler.bundle()
|
||||
.on('error', HandleErrors.handler)
|
||||
.pipe(HandleErrors())
|
||||
.pipe(Source(outFile))
|
||||
.pipe(Buffer())
|
||||
.pipe(FixJavaScriptCore())
|
||||
.pipe(Utils.uglify('build', flags))
|
||||
.pipe(Optimizejs({
|
||||
sourceMap: false
|
||||
}))
|
||||
.on('data', function (file) {
|
||||
if (needHandleWebview) {
|
||||
let contents = file.contents.toString();
|
||||
if (WEBVIEW_REGEXP.test(contents)) {
|
||||
throw new Error('WebView field still exists in engine');
|
||||
}
|
||||
}
|
||||
})
|
||||
.pipe(Gulp.dest(outDir))
|
||||
.on('end', callback);
|
||||
};
|
||||
|
||||
exports.buildJsbMin = function (sourceFile, outputFile, excludes, opt_macroFlags, callback, createMap) {
|
||||
if (typeof opt_macroFlags === 'function') {
|
||||
callback = opt_macroFlags;
|
||||
opt_macroFlags = null;
|
||||
}
|
||||
|
||||
var opts = {
|
||||
sourcemaps: createMap !== false
|
||||
};
|
||||
|
||||
let flags = Object.assign({ jsb: true }, opt_macroFlags);
|
||||
let macro = Utils.getMacros('build', flags);
|
||||
let nativeRenderer = macro["CC_NATIVERENDERER"];
|
||||
let needHandleWebview = excludedWebView(excludes);
|
||||
|
||||
if (opt_macroFlags && nativeRenderer) {
|
||||
opts.aliasifyConfig = jsbAliasify;
|
||||
}
|
||||
if (needHandleWebview) {
|
||||
opts.aliasifyConfig = opts.aliasifyConfig || jsbAliasify;
|
||||
// this will replace require call with an empty object
|
||||
opts.aliasifyConfig.replacements['.*CCWebView(\.js)?'] = false;
|
||||
}
|
||||
|
||||
var FixJavaScriptCore = require('../util/fix-jsb-javascriptcore');
|
||||
|
||||
var outFile = Path.basename(outputFile);
|
||||
var outDir = Path.dirname(outputFile);
|
||||
|
||||
var bundler = createBundler(sourceFile, opts);
|
||||
buildSkipModules.concat(physicsSkipModules).forEach(function (file) {
|
||||
bundler.exclude(require.resolve(file));
|
||||
});
|
||||
if (nativeRenderer) {
|
||||
excludes = excludes.concat(jsbSkipModules);
|
||||
}
|
||||
excludes.forEach(function (module) {
|
||||
bundler.exclude(require.resolve(module));
|
||||
});
|
||||
|
||||
bundler.exclude(Path.resolve(__dirname, '../../DebugInfos.json'));
|
||||
|
||||
bundler.bundle()
|
||||
.on('error', HandleErrors.handler)
|
||||
.pipe(HandleErrors())
|
||||
.pipe(Source(outFile))
|
||||
.pipe(Buffer())
|
||||
.pipe(FixJavaScriptCore())
|
||||
.pipe(Utils.uglify('build', flags))
|
||||
.pipe(Optimizejs({
|
||||
sourceMap: false
|
||||
}))
|
||||
.on('data', function (file) {
|
||||
if (needHandleWebview) {
|
||||
let contents = file.contents.toString();
|
||||
if (WEBVIEW_REGEXP.test(contents)) {
|
||||
throw new Error('WebView field still exists in engine');
|
||||
}
|
||||
}
|
||||
})
|
||||
.pipe(Gulp.dest(outDir))
|
||||
.on('end', callback);
|
||||
};
|
||||
|
||||
exports.buildRuntime = function (sourceFile, outputFile, excludes, opt_macroFlags, callback, createMap) {
|
||||
if (typeof opt_macroFlags === 'function') {
|
||||
callback = opt_macroFlags;
|
||||
opt_macroFlags = null;
|
||||
}
|
||||
|
||||
var opts = {
|
||||
sourcemaps: createMap !== false
|
||||
};
|
||||
|
||||
let flags = Object.assign({ jsb: false, runtime: true, debug: true }, opt_macroFlags);
|
||||
let macro = Utils.getMacros('build', flags);
|
||||
let nativeRenderer = macro["CC_NATIVERENDERER"];
|
||||
|
||||
if (opt_macroFlags && nativeRenderer) {
|
||||
opts.aliasifyConfig = jsbAliasify;
|
||||
}
|
||||
|
||||
var FixJavaScriptCore = require('../util/fix-jsb-javascriptcore');
|
||||
|
||||
var outFile = Path.basename(outputFile);
|
||||
var outDir = Path.dirname(outputFile);
|
||||
|
||||
var bundler = createBundler(sourceFile, opts);
|
||||
buildSkipModules.concat(physicsSkipModules).forEach(function (file) {
|
||||
bundler.exclude(require.resolve(file));
|
||||
});
|
||||
excludes.forEach(function (module) {
|
||||
bundler.exclude(require.resolve(module));
|
||||
});
|
||||
|
||||
bundler.bundle()
|
||||
.on('error', HandleErrors.handler)
|
||||
.pipe(HandleErrors())
|
||||
.pipe(Source(outFile))
|
||||
.pipe(Buffer())
|
||||
.pipe(FixJavaScriptCore())
|
||||
.pipe(Utils.uglify('build', flags))
|
||||
.pipe(Optimizejs({
|
||||
sourceMap: false
|
||||
}))
|
||||
.pipe(Gulp.dest(outDir))
|
||||
.on('end', callback);
|
||||
};
|
||||
|
||||
exports.buildRuntimeMin = function (sourceFile, outputFile, excludes, opt_macroFlags, callback, createMap) {
|
||||
if (typeof opt_macroFlags === 'function') {
|
||||
callback = opt_macroFlags;
|
||||
opt_macroFlags = null;
|
||||
}
|
||||
|
||||
var opts = {
|
||||
sourcemaps: createMap !== false
|
||||
};
|
||||
|
||||
let flags = Object.assign({ jsb: false, runtime: true }, opt_macroFlags);
|
||||
let macro = Utils.getMacros('build', flags);
|
||||
let nativeRenderer = macro["CC_NATIVERENDERER"];
|
||||
|
||||
if (opt_macroFlags && nativeRenderer) {
|
||||
opts.aliasifyConfig = jsbAliasify;
|
||||
}
|
||||
|
||||
var FixJavaScriptCore = require('../util/fix-jsb-javascriptcore');
|
||||
|
||||
var outFile = Path.basename(outputFile);
|
||||
var outDir = Path.dirname(outputFile);
|
||||
|
||||
var bundler = createBundler(sourceFile, opts);
|
||||
buildSkipModules.concat(physicsSkipModules).forEach(function (file) {
|
||||
bundler.exclude(require.resolve(file));
|
||||
});
|
||||
excludes.forEach(function (module) {
|
||||
bundler.exclude(require.resolve(module));
|
||||
});
|
||||
|
||||
bundler.exclude(Path.resolve(__dirname, '../../DebugInfos.json'));
|
||||
|
||||
bundler.bundle()
|
||||
.on('error', HandleErrors.handler)
|
||||
.pipe(HandleErrors())
|
||||
.pipe(Source(outFile))
|
||||
.pipe(Buffer())
|
||||
.pipe(FixJavaScriptCore())
|
||||
.pipe(Utils.uglify('build', flags))
|
||||
.pipe(Optimizejs({
|
||||
sourceMap: false
|
||||
}))
|
||||
.pipe(Gulp.dest(outDir))
|
||||
.on('end', callback);
|
||||
};
|
||||
|
||||
exports.excludeAllDepends = function (excludedModules) {
|
||||
let modules = Fs.readJsonSync(Path.join(__dirname, '../../modules.json'));
|
||||
if (modules && modules.length > 0) {
|
||||
function _excludeMudules (muduleName) {
|
||||
if (excMudules[muduleName]) {
|
||||
return;
|
||||
}
|
||||
for (let module of modules) {
|
||||
if (module.name === muduleName) {
|
||||
excMudules[muduleName] = module;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
modules.forEach(module => {
|
||||
if (module.dependencies && module.dependencies.indexOf(muduleName) !== -1) {
|
||||
_excludeMudules(module.name);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// exclude all mudules
|
||||
let excMudules = Object.create(null);
|
||||
|
||||
excludedModules.forEach(_excludeMudules);
|
||||
|
||||
let excludes = [];
|
||||
for (let key in excMudules) {
|
||||
let module = excMudules[key];
|
||||
if (module.entries) {
|
||||
module.entries.forEach(function (file) {
|
||||
let path = Path.join(__dirname, '..', '..', file);
|
||||
if (excludes.indexOf(path) === -1) {
|
||||
excludes.push(path);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return excludes;
|
||||
}
|
||||
else {
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
exports.jsbSkipModules = jsbSkipModules;
|
||||
169
engine/gulp/tasks/test.js
Normal file
169
engine/gulp/tasks/test.js
Normal file
@@ -0,0 +1,169 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
const UGLIFY = false;
|
||||
|
||||
'use strict';
|
||||
|
||||
const Path = require('path');
|
||||
const Fs = require('fs');
|
||||
const Source = require('vinyl-source-stream');
|
||||
const Gulp = require('gulp');
|
||||
const Fb = require('gulp-fb');
|
||||
const Babel = require('gulp-babel');
|
||||
const Buffer = require('vinyl-buffer');
|
||||
const HandleErrors = require('../util/handleErrors');
|
||||
const Es = require('event-stream');
|
||||
|
||||
const Sourcemaps = require('gulp-sourcemaps');
|
||||
|
||||
const Utils = require('../util/utils');
|
||||
const createBundler = require('../util/create-bundler');
|
||||
|
||||
exports.build = function (sourceFile, outputFile, sourceFileForExtends, outputFileForExtends, sourcemaps, callback) {
|
||||
var cacheDir = Path.resolve(Path.dirname(outputFile), '.cache/test-compile-cache');
|
||||
var engine = createBundler(sourceFile, {
|
||||
sourcemaps: sourcemaps,
|
||||
cacheDir: cacheDir
|
||||
})
|
||||
.bundle()
|
||||
.on('error', HandleErrors.handler)
|
||||
.pipe(HandleErrors())
|
||||
.pipe(Source(Path.basename(outputFile)))
|
||||
.pipe(Buffer());
|
||||
|
||||
if (UGLIFY) {
|
||||
if (sourcemaps) {
|
||||
engine = engine.pipe(Sourcemaps.init({loadMaps: true}));
|
||||
}
|
||||
|
||||
// remove `...args` used in CC_JSB
|
||||
engine = engine.pipe(Utils.uglify('test'));
|
||||
|
||||
if (sourcemaps) {
|
||||
engine = engine.pipe(Sourcemaps.write('./', {
|
||||
sourceRoot: '../',
|
||||
includeContent: false,
|
||||
addComment: true
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
engine = engine.pipe(Gulp.dest(Path.dirname(outputFile)));
|
||||
|
||||
if (Fs.existsSync(sourceFileForExtends)) {
|
||||
var engineExtends = createBundler(sourceFileForExtends, {
|
||||
presets: [
|
||||
[
|
||||
require('@babel/preset-env'),
|
||||
{
|
||||
loose: true,
|
||||
// bugfixes: true, since babel 7.9
|
||||
targets: 'PhantomJS 2.1',
|
||||
}
|
||||
],
|
||||
],
|
||||
plugins: [
|
||||
require('@babel/plugin-transform-runtime')
|
||||
],
|
||||
sourcemaps,
|
||||
cacheDir,
|
||||
bundleExternal: true,
|
||||
})
|
||||
.bundle()
|
||||
.on('error', HandleErrors.handler)
|
||||
.pipe(HandleErrors())
|
||||
.pipe(Source(Path.basename(outputFileForExtends)))
|
||||
.pipe(Buffer())
|
||||
.pipe(Gulp.dest(Path.dirname(outputFileForExtends)));
|
||||
Es.merge(engine, engineExtends).on('end', callback);
|
||||
}
|
||||
else {
|
||||
engine.on('end', callback);
|
||||
}
|
||||
};
|
||||
|
||||
exports.unit = function (outDir, libs, callback) {
|
||||
var title = 'CocosCreator Engine Test Suite';
|
||||
if (Fs.existsSync('./bin/cocos2d-js-extends-for-test.js')) {
|
||||
libs.push('./bin/cocos2d-js-extends-for-test.js');
|
||||
title += ' (Editor Extends Included)';
|
||||
}
|
||||
return Gulp.src(['test/qunit/unit-es5/**/*.js', './bin/test/**/*.js'], { read: false, base: './' })
|
||||
.pipe(Fb.toFileList())
|
||||
.pipe(Fb.generateRunner('test/qunit/lib/qunit-runner.html', outDir, title, libs))
|
||||
.pipe(Gulp.dest(outDir))
|
||||
.on('end', callback);
|
||||
};
|
||||
|
||||
exports.test = function (callback) {
|
||||
var qunit;
|
||||
try {
|
||||
qunit = require('gulp-qunit');
|
||||
} catch (e) {
|
||||
console.error('Please run "npm install gulp-qunit@2.0.1 -g" before running "gulp test".');
|
||||
throw e;
|
||||
}
|
||||
return Gulp.src('bin/qunit-runner.html')
|
||||
.pipe(qunit({ timeout: 15 }))
|
||||
.on('end', callback);
|
||||
};
|
||||
|
||||
exports.buildTestCase = function (outDir, callback) {
|
||||
return Gulp.src('test/qunit/unit/**/*.js')
|
||||
.pipe(Babel({
|
||||
presets: [
|
||||
[
|
||||
require('@babel/preset-env'),
|
||||
{
|
||||
"loose": true,
|
||||
// "bugfixes": true, since babel 7.9
|
||||
"targets": "PhantomJS 2.1"
|
||||
}
|
||||
]
|
||||
],
|
||||
plugins: [
|
||||
// make sure that transform-decorators-legacy comes before transform-class-properties.
|
||||
[
|
||||
require('@babel/plugin-proposal-decorators'),
|
||||
{ legacy: true },
|
||||
],
|
||||
[
|
||||
require('@babel/plugin-proposal-class-properties'),
|
||||
{ loose: true },
|
||||
],
|
||||
[
|
||||
require('babel-plugin-add-module-exports'),
|
||||
],
|
||||
],
|
||||
ast: false,
|
||||
babelrc: false,
|
||||
highlightCode: false,
|
||||
sourceMap: true,
|
||||
compact: false
|
||||
}))
|
||||
.pipe(Gulp.dest(outDir))
|
||||
.on('end', callback);
|
||||
};
|
||||
108
engine/gulp/tasks/watch.js
Normal file
108
engine/gulp/tasks/watch.js
Normal file
@@ -0,0 +1,108 @@
|
||||
var Watchify = require('watchify');
|
||||
var Browserify = require('browserify');
|
||||
var Fs = require('fs');
|
||||
|
||||
var Path = require('path');
|
||||
var through = require('through');
|
||||
|
||||
var Engine = require('./engine');
|
||||
|
||||
// var source = require('vinyl-source-stream');
|
||||
// var buffer = require('vinyl-buffer');
|
||||
// var sourcemaps = require('gulp-sourcemaps');
|
||||
|
||||
function watchFile(opts) {
|
||||
var bundler = new Browserify(opts.entries, {
|
||||
cache: {},
|
||||
packageCache: {},
|
||||
debug: true,
|
||||
detectGlobals: false, // dont insert `process`, `global`, `__filename`, and `__dirname`
|
||||
bundleExternal: false, // dont bundle external modules
|
||||
plugin: [Watchify]
|
||||
});
|
||||
|
||||
bundler.on('update', bundle);
|
||||
|
||||
if (opts.skips) {
|
||||
var skips = opts.skips;
|
||||
for (var i = 0; i < skips.length; ++i) {
|
||||
var file = require.resolve(skips[i]);
|
||||
bundler.ignore(file);
|
||||
}
|
||||
}
|
||||
|
||||
function bundle() {
|
||||
var name = new Date().toTimeString() + ' : browserify for ' + opts.dest + '. ';
|
||||
console.time(name);
|
||||
|
||||
// append prefix to index.js
|
||||
var prefix = '';
|
||||
if (opts.prefix) {
|
||||
if (typeof opts.prefix === 'function') {
|
||||
prefix = opts.prefix();
|
||||
}
|
||||
else if (typeof opts.prefix === 'string') {
|
||||
prefix = opts.prefix;
|
||||
}
|
||||
}
|
||||
|
||||
bundler.transform(function (file) {
|
||||
var data = '';
|
||||
|
||||
if (Path.basename(file) === 'index.js') {
|
||||
data += prefix;
|
||||
}
|
||||
|
||||
return through(write, end);
|
||||
|
||||
function write (buf) { data += buf; }
|
||||
function end () {
|
||||
this.queue(data);
|
||||
this.queue(null);
|
||||
}
|
||||
return;
|
||||
});
|
||||
|
||||
// do bundle
|
||||
var b = bundler.bundle();
|
||||
|
||||
b.on('end', function () {
|
||||
console.timeEnd(name);
|
||||
});
|
||||
|
||||
b = b.pipe(Fs.createWriteStream(opts.dest));
|
||||
|
||||
// fixed chinese character in source maps
|
||||
// b = b.pipe(source(Path.basename(opts.dest)))
|
||||
// .pipe(buffer())
|
||||
// .pipe(sourcemaps.init({loadMaps: true}))
|
||||
// .pipe(sourcemaps.write('./'))
|
||||
// .pipe(gulp.dest(Path.dirname(opts.dest)));
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
return bundle();
|
||||
}
|
||||
|
||||
exports.preview = function (sourceFile, outputFile) {
|
||||
return watchFile({
|
||||
entries: sourceFile,
|
||||
dest: outputFile,
|
||||
prefix: 'CC_DEV = true;\n'
|
||||
});
|
||||
};
|
||||
|
||||
exports.jsbPolyfill = function (sourceFile, outputFile) {
|
||||
return watchFile({
|
||||
entries: sourceFile,
|
||||
dest: outputFile,
|
||||
prefix: function () {
|
||||
var prefix = 'CC_DEV = true;\n';
|
||||
prefix += 'CC_JSB = true;\n';
|
||||
|
||||
return prefix;
|
||||
},
|
||||
skips: Engine.jsbSkipModules
|
||||
});
|
||||
};
|
||||
182
engine/gulp/util/create-bundler.js
Normal file
182
engine/gulp/util/create-bundler.js
Normal file
@@ -0,0 +1,182 @@
|
||||
'use strict';
|
||||
|
||||
const Path = require('path');
|
||||
allowReturnOutsideFunctionInBrowserifyTransform();
|
||||
const Fs = require('fs');
|
||||
const Del = require('del');
|
||||
|
||||
const dropPureExport = require('./drop-pure-export');
|
||||
const inlineProp = require('./inline-prop');
|
||||
const polyfillPromisify = require('./polyfill-node-promisify');
|
||||
|
||||
const preludePath = Path.resolve(__dirname, '../browserify_prelude.js');
|
||||
const prelude = Fs.readFileSync(preludePath, 'utf8');
|
||||
|
||||
function allowReturnOutsideFunctionInBrowserifyTransform () {
|
||||
var paths = [
|
||||
'browserify/node_modules/syntax-error/node_modules/acorn',
|
||||
'syntax-error/node_modules/acorn',
|
||||
'acorn'
|
||||
];
|
||||
function patch (path) {
|
||||
var acorn = require(path);
|
||||
var parse = acorn.parse;
|
||||
if (typeof parse === 'function') {
|
||||
if (acorn.parse.name !== 'monkeyPatchedParse') {
|
||||
acorn.parse = function monkeyPatchedParse(input, options) {
|
||||
if (options) {
|
||||
options.allowReturnOutsideFunction = true;
|
||||
}
|
||||
else {
|
||||
options = {
|
||||
allowReturnOutsideFunction: true
|
||||
};
|
||||
}
|
||||
return parse(input, options);
|
||||
};
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.error('Can not find acorn.parse to patch');
|
||||
}
|
||||
}
|
||||
|
||||
var patched = false;
|
||||
for (var i = 0; i < paths.length; i++) {
|
||||
try {
|
||||
patch(paths[i]);
|
||||
patched = true;
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
}
|
||||
if (!patched) {
|
||||
console.error('Can not find acorn to patch');
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @param [options.sourcemaps = true]
|
||||
* @param [options.babelifyOpt]
|
||||
* @param [options.aliasifyConfig]
|
||||
*/
|
||||
module.exports = function createBundler(entryFiles, options) {
|
||||
|
||||
// Ignore IDE compiled JavaScript files
|
||||
Del.sync('./cocos2d/core/platform/deserialize-compiled.js');
|
||||
Del.sync('./cocos2d/core/value-types/*.js');
|
||||
|
||||
// https://github.com/substack/node-browserify#methods
|
||||
var browserifyOpt = {
|
||||
extensions: ['.js', '.json', '.ts'],
|
||||
entries: [].concat(entryFiles),
|
||||
debug: (options && 'sourcemaps' in options) ? options.sourcemaps : true,
|
||||
detectGlobals: false, // dont insert `process`, `global`, `__filename`, and `__dirname`
|
||||
bundleExternal: !!(options && options.bundleExternal) || false, // dont bundle external modules
|
||||
//standalone: 'engine-framework',
|
||||
//basedir: tempScriptDir
|
||||
|
||||
// define custom prelude to optimize script evaluate time
|
||||
prelude: prelude,
|
||||
preludePath: Path.relative(process.cwd(), preludePath),
|
||||
};
|
||||
|
||||
var presets = [
|
||||
[
|
||||
require('@babel/preset-env'),
|
||||
{
|
||||
"loose": true,
|
||||
// "bugfixes": true, since babel 7.9
|
||||
}
|
||||
],
|
||||
{
|
||||
plugins: [
|
||||
[
|
||||
require('@babel/plugin-proposal-decorators'),
|
||||
{ legacy: true },
|
||||
],
|
||||
[
|
||||
require('@babel/plugin-proposal-class-properties'),
|
||||
{ loose: true },
|
||||
],
|
||||
]
|
||||
},
|
||||
[
|
||||
require('@babel/preset-typescript'),
|
||||
{
|
||||
allowDeclareFields: true,
|
||||
}
|
||||
],
|
||||
];
|
||||
|
||||
var plugins = [
|
||||
// // < 6.16.0
|
||||
// [ 'babel-plugin-parser-opts', { allowReturnOutsideFunction: true } ]
|
||||
[
|
||||
require('babel-plugin-const-enum'),
|
||||
{ transform: "constObject" },
|
||||
],
|
||||
[
|
||||
require('babel-plugin-add-module-exports'),
|
||||
],
|
||||
];
|
||||
|
||||
var Babelify;
|
||||
try {
|
||||
Babelify = require('babelify');
|
||||
} catch (e) {
|
||||
console.error('Please run "npm install babelify".');
|
||||
throw e;
|
||||
}
|
||||
var aliasify;
|
||||
try {
|
||||
aliasify = require('aliasify');
|
||||
} catch (e) {
|
||||
console.error('Please run "npm install aliasify".');
|
||||
throw e;
|
||||
}
|
||||
|
||||
var b;
|
||||
if (options && options.cacheDir) {
|
||||
// https://github.com/royriojas/persistify
|
||||
const Persistify = require('persistify');
|
||||
b = Persistify(browserifyOpt, {
|
||||
recreate: false,
|
||||
cacheId: require('../../package.json').version + entryFiles,
|
||||
cacheDir: options.cacheDir
|
||||
});
|
||||
}
|
||||
else {
|
||||
const Browserify = require('browserify');
|
||||
b = new Browserify(browserifyOpt);
|
||||
}
|
||||
|
||||
b = b.exclude(Path.join(__dirname, '../../package.json'));
|
||||
|
||||
if (browserifyOpt.bundleExternal) {
|
||||
b = b.transform(polyfillPromisify);
|
||||
}
|
||||
|
||||
return b
|
||||
.transform(dropPureExport)
|
||||
.transform(inlineProp.inlineConst)
|
||||
.transform(Babelify, (options && options.babelifyOpt) || {
|
||||
extensions: ['.ts', '.js'],
|
||||
presets: (options && options.presets) || presets,
|
||||
plugins: (options && options.plugins && options.plugins.concat(plugins)) || plugins,
|
||||
|
||||
// >= 6.16.0
|
||||
// parserOpts: {
|
||||
// allowReturnOutsideFunction: true,
|
||||
// },
|
||||
|
||||
comments: true,
|
||||
ast: false,
|
||||
babelrc: false,
|
||||
highlightCode: false,
|
||||
sourceMaps: true,
|
||||
compact: false
|
||||
})
|
||||
.transform(inlineProp.inlineEnum)
|
||||
.transform(aliasify, (options && options.aliasifyConfig) || {});
|
||||
};
|
||||
45
engine/gulp/util/drop-pure-export.js
Normal file
45
engine/gulp/util/drop-pure-export.js
Normal file
@@ -0,0 +1,45 @@
|
||||
|
||||
// Drop unused `export` syntax to indicate that the object will only be used inside the module at runtime.
|
||||
// So the expression can be evaluated by uglify.
|
||||
//
|
||||
// Replace:
|
||||
// /*@__DROP_PURE_EXPORT__*/
|
||||
// export xxx
|
||||
// As:
|
||||
// /*@__DROP_PURE_EXPORT__*/
|
||||
// xxx
|
||||
|
||||
const es = require('event-stream');
|
||||
const stream = require('stream');
|
||||
|
||||
const COMMENT_ANNOTATION = `/*@__DROP_PURE_EXPORT__*/`;
|
||||
const REG = /(\/\*@__DROP_PURE_EXPORT__\*\/\s*)(export\s+)?/g;
|
||||
|
||||
module.exports = function (filename) {
|
||||
if (filename.endsWith('.js') || filename.endsWith('.ts')) {
|
||||
return es.map(function (data, callback) {
|
||||
var content = data.toString();
|
||||
if (content.includes(COMMENT_ANNOTATION)) { // fast test
|
||||
let error = false;
|
||||
content = content.replace(REG, function (match, g1, g2) {
|
||||
if (g2) {
|
||||
return g1;
|
||||
}
|
||||
else {
|
||||
// console.log(content);
|
||||
error = true;
|
||||
return match;
|
||||
}
|
||||
});
|
||||
if (error) {
|
||||
return callback(new Error(`Uncaptured comment annotation "${COMMENT_ANNOTATION}" in "${filename}", please use it in the correct way.`));
|
||||
}
|
||||
data = new Buffer(content);
|
||||
}
|
||||
callback(null, data);
|
||||
});
|
||||
}
|
||||
else {
|
||||
return stream.PassThrough();
|
||||
}
|
||||
};
|
||||
42
engine/gulp/util/fix-jsb-javascriptcore.js
Normal file
42
engine/gulp/util/fix-jsb-javascriptcore.js
Normal file
@@ -0,0 +1,42 @@
|
||||
|
||||
// fix `typeof constructor` on JavaScriptCore
|
||||
|
||||
const ES = require('event-stream');
|
||||
const Path = require('path');
|
||||
|
||||
const getRealTypeOfObj = (function __realTypeOfObj (obj) {
|
||||
if (obj) {
|
||||
if (obj.toString) {
|
||||
if (obj.toString() === '[object CallbackConstructor]')
|
||||
return 'function';
|
||||
}
|
||||
else {
|
||||
// "Cannot convert object to primitive value"
|
||||
}
|
||||
}
|
||||
return 'object';
|
||||
}).toString();
|
||||
|
||||
const TYPEOF_SHIM = `\n${getRealTypeOfObj}\nvar __typeofVal = "";`;
|
||||
|
||||
const TYPEOF_REG = /typeof\s+([$A-Za-z_][0-9A-Za-z_$\.\[\]]*)([\s!=;\)])/g;
|
||||
const TYPEOF_REPLACEMENT = '(__typeofVal = typeof $1, __typeofVal === "object" ? __realTypeOfObj($1) : __typeofVal)$2';
|
||||
|
||||
const SUPPORT_JSC = false;
|
||||
|
||||
module.exports = function () {
|
||||
return ES.through(function (file) {
|
||||
if (Path.extname(file.path) === '.js' && SUPPORT_JSC) {
|
||||
var content = file.contents.toString();
|
||||
|
||||
content = content.replace(TYPEOF_REG, TYPEOF_REPLACEMENT);
|
||||
content += TYPEOF_SHIM;
|
||||
|
||||
// make shim as local variables so that variable names will be mangled
|
||||
content = '(function () {' + content + '})();';
|
||||
|
||||
file.contents = new Buffer(content);
|
||||
}
|
||||
this.emit('data', file);
|
||||
});
|
||||
};
|
||||
52
engine/gulp/util/handleErrors.js
Normal file
52
engine/gulp/util/handleErrors.js
Normal file
@@ -0,0 +1,52 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
// https://github.com/GoodBoyDigital/pixi.js/blob/c984191777001580b3a81f41cfe354b58d99757f/gulp/util/handleErrors.js
|
||||
var gutil = require('gulp-util'),
|
||||
plumber = require('gulp-plumber'),
|
||||
ERROR = gutil.colors.red('[ERROR]');
|
||||
|
||||
function errorHandler(err) {
|
||||
var msg = err.toString();
|
||||
|
||||
if (msg === '[object Object]') {
|
||||
msg = err;
|
||||
}
|
||||
|
||||
gutil.log(ERROR, err);
|
||||
|
||||
if (err.stack) {
|
||||
gutil.log(ERROR, err.stack);
|
||||
}
|
||||
|
||||
// Keep gulp from hanging on this task
|
||||
this.emit('end');
|
||||
}
|
||||
|
||||
module.exports = function () {
|
||||
return plumber(errorHandler);
|
||||
};
|
||||
|
||||
module.exports.handler = errorHandler;
|
||||
109
engine/gulp/util/inline-prop.js
Normal file
109
engine/gulp/util/inline-prop.js
Normal file
@@ -0,0 +1,109 @@
|
||||
|
||||
// Force inline const enum.
|
||||
// We don't use terser >= 4.2.1 to do this because it obsoleted `reduce_funcs` option.
|
||||
//
|
||||
// Replace:
|
||||
// /*@__DROP_PURE_EXPORT__*/
|
||||
// var aa = {
|
||||
// bb: 0,
|
||||
// cc: 1,
|
||||
// };
|
||||
// const UPPER_CASE = 2;
|
||||
// console.log(aa.bb, aa.cc, UPPER_CASE);
|
||||
//
|
||||
// As:
|
||||
// /*@__DROP_PURE_EXPORT__*/
|
||||
// var aa = {
|
||||
// bb: 0,
|
||||
// cc: 1,
|
||||
// };
|
||||
// const UPPER_CASE = 2;
|
||||
// console.log(0, 1, 2);
|
||||
|
||||
const es = require('event-stream');
|
||||
const stream = require('stream');
|
||||
|
||||
const COMMENT_ANNOTATION = `/*@__DROP_PURE_EXPORT__*/`;
|
||||
const CONST_OBJ_REG = /^[ \t]*\/\*@__DROP_PURE_EXPORT__\*\/[\w\s]*?\s+([A-Za-z_$][0-9A-Za-z_$]*)\s*=\s*({[\n\s\S]*?})/gm;
|
||||
const CONST_NUM_REG = /^[ \t]*const[ \t]+([A-Z_$][0-9A-Z_$]*)[ \t]*=[ \t]*(\d{1,2});?$/gm;
|
||||
|
||||
function matchAll (str, reg, callback) {
|
||||
// the easiest matchAll polyfill ; )
|
||||
if (!reg.global) {
|
||||
throw new Error('Can not matchAll if the global property is false.');
|
||||
}
|
||||
str.replace(reg, function (m) {
|
||||
callback.apply(null, arguments);
|
||||
return m;
|
||||
});
|
||||
}
|
||||
|
||||
exports.inlineEnum = function (filename) {
|
||||
if (filename.endsWith('.js') || filename.endsWith('.ts')) {
|
||||
return es.map(function (data, callback) {
|
||||
var content = data.toString();
|
||||
if (content.includes(COMMENT_ANNOTATION)) { // fast test
|
||||
let error = null;
|
||||
matchAll(content, CONST_OBJ_REG, function (match, obj, body) {
|
||||
try {
|
||||
body = Function(`return ${body}`)();
|
||||
}
|
||||
catch (e) {
|
||||
error = new Error(`Failed to inline property "${obj}" in "${filename}", ${e}`);
|
||||
return;
|
||||
}
|
||||
for (const key in body) {
|
||||
let reg = new RegExp(`\\b${obj}\\.${key}\\b`, 'g');
|
||||
let replaced = content.replace(reg, body[key]);
|
||||
if (replaced !== content) {
|
||||
content = replaced;
|
||||
console.log(`[inline-prop] '${obj}.${key}' is inlined with ${body[key]}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (error) {
|
||||
return callback(error);
|
||||
}
|
||||
data = new Buffer(content);
|
||||
}
|
||||
callback(null, data);
|
||||
});
|
||||
}
|
||||
else {
|
||||
return stream.PassThrough();
|
||||
}
|
||||
};
|
||||
|
||||
exports.inlineConst = function (filename) {
|
||||
if (filename.endsWith('.js') || filename.endsWith('.ts')) {
|
||||
return es.map(function (data, callback) {
|
||||
var content = data.toString();
|
||||
if (content.includes(COMMENT_ANNOTATION)) { // fast test
|
||||
let error = null;
|
||||
matchAll(content, CONST_NUM_REG, function (match, name, value) {
|
||||
let reg = new RegExp(`([{,]\\s*|\\btypeof[ \\t]+)?(\\b${name}\\b)(?![ \\t]*=)`, 'g'); // not support negative lookbehind...
|
||||
let replaced = content.replace(reg, function (m, g1, g2) {
|
||||
if (m === g2) {
|
||||
return value;
|
||||
}
|
||||
else {
|
||||
return m;
|
||||
}
|
||||
});
|
||||
if (replaced !== content) {
|
||||
content = replaced;
|
||||
console.log(`[inline-prop] '${name}' is inlined with ${value}`);
|
||||
}
|
||||
});
|
||||
if (error) {
|
||||
return callback(error);
|
||||
}
|
||||
data = new Buffer(content);
|
||||
}
|
||||
callback(null, data);
|
||||
});
|
||||
}
|
||||
else {
|
||||
return stream.PassThrough();
|
||||
}
|
||||
};
|
||||
44
engine/gulp/util/polyfill-node-promisify.js
Normal file
44
engine/gulp/util/polyfill-node-promisify.js
Normal file
@@ -0,0 +1,44 @@
|
||||
|
||||
// Replace node promisify for testing editor-extends.
|
||||
//
|
||||
// Replace:
|
||||
// require('util')
|
||||
// As:
|
||||
// { promisify }
|
||||
|
||||
const es = require('event-stream');
|
||||
const stream = require('stream');
|
||||
|
||||
const promisify = (function (handle) {
|
||||
return function (...args) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
handle(...args, (err, res) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
}
|
||||
else {
|
||||
resolve(res);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
}).toString();
|
||||
|
||||
const REPLACE = /require\(['"]util['"]\)/g;
|
||||
const AS = `{promisify:${promisify}}`;
|
||||
|
||||
module.exports = function (filename) {
|
||||
if (filename.endsWith('.js') || filename.endsWith('.ts')) {
|
||||
return es.map(function (data, callback) {
|
||||
var content = data.toString();
|
||||
if (REPLACE.test(content)) { // fast test
|
||||
content = content.replace(REPLACE, AS);
|
||||
data = new Buffer(content);
|
||||
}
|
||||
callback(null, data);
|
||||
});
|
||||
}
|
||||
else {
|
||||
return stream.PassThrough();
|
||||
}
|
||||
};
|
||||
202
engine/gulp/util/utils.js
Normal file
202
engine/gulp/util/utils.js
Normal file
@@ -0,0 +1,202 @@
|
||||
|
||||
const PLATFORM_MACROS = ['CC_EDITOR', 'CC_PREVIEW', 'CC_BUILD', 'CC_TEST'];
|
||||
const FLAGS = ['support_jit', 'jsb', 'runtime', 'debug', 'nativeRenderer', 'minigame', 'physics_builtin', 'physics_cannon'];
|
||||
|
||||
// generate macros for uglify's global_defs
|
||||
// available platforms: 'editor' | 'preview' | 'build' | 'test'
|
||||
// available keys of flags: 'jsb' | 'runtime' | 'minigame' | 'debug' | 'nativeRenderer'
|
||||
exports.getMacros = function (platform, flags) {
|
||||
// platform macros
|
||||
var platformMacro = 'CC_' + platform.toUpperCase();
|
||||
if (PLATFORM_MACROS.indexOf(platformMacro) === -1) {
|
||||
throw new Error('Unknown platform: ' + platform);
|
||||
}
|
||||
var res = {};
|
||||
for (let i = 0; i < PLATFORM_MACROS.length; i++) {
|
||||
let macro = PLATFORM_MACROS[i];
|
||||
res[macro] = (macro === platformMacro);
|
||||
}
|
||||
|
||||
// flag macros
|
||||
if (flags) {
|
||||
for (let flag in flags) {
|
||||
if (flags.hasOwnProperty(flag) && flags[flag]) {
|
||||
if (FLAGS.indexOf(flag) === -1) {
|
||||
throw new Error('Unknown flag: ' + flag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < FLAGS.length; i++) {
|
||||
let flag = FLAGS[i];
|
||||
let macro = 'CC_' + flag.toUpperCase();
|
||||
res[macro] = !!(flags && flags[flag]);
|
||||
}
|
||||
|
||||
// debug macros
|
||||
res['CC_DEV'] = res['CC_EDITOR'] || res['CC_PREVIEW'] || res['CC_TEST'];
|
||||
res['CC_DEBUG'] = res['CC_DEBUG'] || res['CC_DEV'];
|
||||
res['CC_SUPPORT_JIT'] = !(res['CC_RUNTIME'] || res['CC_MINIGAME']);
|
||||
res['CC_NATIVERENDERER'] = res['CC_JSB'] && true;
|
||||
return res;
|
||||
};
|
||||
|
||||
// see https://github.com/terser/terser#compress-options
|
||||
exports.getUglifyOptions = function (platform, flags) {
|
||||
var global_defs = exports.getMacros(platform, flags);
|
||||
var releaseMode = !global_defs['CC_DEBUG'];
|
||||
|
||||
var optimizeForJSC = releaseMode && global_defs['CC_JSB'];
|
||||
if (optimizeForJSC) {
|
||||
return {
|
||||
parse: {
|
||||
bare_returns: true
|
||||
},
|
||||
toplevel: false,
|
||||
compress: {
|
||||
global_defs: global_defs,
|
||||
negate_iife: false,
|
||||
sequences: false,
|
||||
keep_infinity: true, // reduce jsc file size
|
||||
typeofs: false,
|
||||
inline: true,
|
||||
reduce_funcs: false, // keep single-use function object being cached, but not supported since 4.2.1, see terser/terser#696
|
||||
passes: 2, // first: remove deadcode, second: drop variables
|
||||
keep_fargs: false,
|
||||
unsafe_Function: true,
|
||||
unsafe_math: true,
|
||||
unsafe_methods: true,
|
||||
},
|
||||
output: {
|
||||
beautify: true, // enable preserve_lines for line number
|
||||
indent_level: 0, // reduce jsc file size
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (releaseMode) {
|
||||
return {
|
||||
parse: {
|
||||
bare_returns: true
|
||||
},
|
||||
toplevel: false,
|
||||
compress: {
|
||||
global_defs: global_defs,
|
||||
negate_iife: false,
|
||||
inline: true,
|
||||
reduce_funcs: false, // keep single-use function object being cached, but not supported since 4.2.1, see terser/terser#696
|
||||
passes: 2, // first: remove deadcode, second: reduce constant variables
|
||||
keep_fargs: false,
|
||||
unsafe_Function: true,
|
||||
unsafe_math: true,
|
||||
unsafe_methods: true,
|
||||
},
|
||||
// mangle: false,
|
||||
output: {
|
||||
// http://lisperator.net/uglifyjs/codegen
|
||||
// beautify: true,
|
||||
// indent_level: 2,
|
||||
ascii_only: true,
|
||||
},
|
||||
safari10: true, // cocos-creator/engine#5144
|
||||
};
|
||||
}
|
||||
else {
|
||||
return {
|
||||
parse: {
|
||||
bare_returns: true
|
||||
},
|
||||
toplevel: false,
|
||||
compress: {
|
||||
global_defs: global_defs,
|
||||
negate_iife: false,
|
||||
sequences: false, // join consecutive statements with the “comma operator”
|
||||
properties: false, // optimize property access: a["foo"] → a.foo
|
||||
// dead_code: true, // discard unreachable code
|
||||
drop_debugger: false, // discard “debugger” statements
|
||||
// ecma: 5, // transform ES5 code into smaller ES6+ equivalent forms
|
||||
// evaluate: true, // evaluate constant expressions
|
||||
unsafe: false, // some unsafe optimizations (see below)
|
||||
// computed_props: true,
|
||||
// conditionals: false, // optimize if-s and conditional expressions
|
||||
comparisons: false, // optimize comparisons
|
||||
booleans: false, // optimize boolean expressions
|
||||
typeofs: false, // Transforms typeof foo == "undefined" into foo === void 0. Note: recommend to set this value to false for IE10 and earlier versions due to known issues.
|
||||
loops: false, // optimize loops
|
||||
unused: false, // drop unused variables/functions
|
||||
hoist_funs: false, // hoist function declarations
|
||||
hoist_props: false,
|
||||
hoist_vars: false, // hoist variable declarations
|
||||
if_return: false, // optimize if-s followed by return/continue
|
||||
inline: false, // embed simple functions
|
||||
join_vars: false, // join var declarations
|
||||
collapse_vars: false, // Collapse single-use non-constant variables - side effects permitting.
|
||||
reduce_funcs: false,
|
||||
reduce_vars: false, // Improve optimization on variables assigned with and used as constant values.
|
||||
//warnings: true,
|
||||
pure_getters: false,
|
||||
pure_funcs: null,
|
||||
drop_console: false,
|
||||
// expression: false, // Pass true to preserve completion values from terminal statements without return, e.g. in bookmarklets.
|
||||
keep_fargs: true,
|
||||
keep_fnames: true,
|
||||
keep_infinity: true, // Pass true to prevent Infinity from being compressed into 1/0, which may cause performance issues on Chrome.
|
||||
side_effects: false, // drop side-effect-free statements
|
||||
},
|
||||
mangle: false,
|
||||
//preserveComments: 'all',
|
||||
output: {
|
||||
// http://lisperator.net/uglifyjs/codegen
|
||||
beautify: true,
|
||||
indent_level: 2,
|
||||
ascii_only: true,
|
||||
},
|
||||
safari10: true, // cocos-creator/engine#5144
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
exports.uglify = function (platform, isJSB, isDebugBuild) {
|
||||
const options = exports.getUglifyOptions(platform, isJSB, isDebugBuild);
|
||||
if (false) {
|
||||
const Composer = require('gulp-uglify/composer');
|
||||
const Uglify = require('uglify-es');
|
||||
return Composer(Uglify)(options);
|
||||
}
|
||||
else {
|
||||
const Terser = require("terser");
|
||||
const ES = require('event-stream');
|
||||
const applySourceMap = require('vinyl-sourcemaps-apply');
|
||||
return ES.through(function (file) {
|
||||
if (file.path.endsWith('.js')) {
|
||||
let build;
|
||||
let eachOption;
|
||||
let content = file.contents.toString();
|
||||
if (file.sourceMap && file.sourceMap.file) {
|
||||
build = {};
|
||||
build[file.sourceMap.file] = content;
|
||||
eachOption = Object.assign({}, options, {
|
||||
sourceMap: {
|
||||
filename: file.sourceMap.file,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
build = content;
|
||||
eachOption = options;
|
||||
}
|
||||
|
||||
var result = Terser.minify(build, eachOption);
|
||||
if (result.error) {
|
||||
return this.emit('error', result.error);
|
||||
}
|
||||
content = result.code;
|
||||
|
||||
file.contents = new Buffer(content);
|
||||
if (result.map) {
|
||||
applySourceMap(file, result.map);
|
||||
}
|
||||
}
|
||||
this.emit('data', file);
|
||||
});
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user