初始化

This commit is contained in:
SmallMain
2022-06-25 00:23:03 +08:00
commit ef0589e8e5
2264 changed files with 617829 additions and 0 deletions

View 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) || {});
};

View 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();
}
};

View 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);
});
};

View 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;

View 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();
}
};

View 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
View 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);
});
}
};