/** prelude
|
const serial = require('../util/serial');
|
const relateContext = require('../util/relate-context');
|
|
const LocalModule = require('webpack/lib/dependencies/LocalModule');
|
|
function flattenPrototype(obj) {
|
if (typeof obj === 'string') {
|
return obj;
|
}
|
const copy = {};
|
for (const key in obj) {
|
copy[key] = obj[key];
|
}
|
return copy;
|
}
|
|
const assignTruthful = {
|
freeze(arg, dependency) {
|
return arg;
|
},
|
thaw(arg, frozen) {
|
return arg;
|
},
|
};
|
|
const assignDefined = {
|
freeze(arg, dependency) {
|
if (typeof arg !== 'undefined') {
|
return arg;
|
}
|
},
|
thaw(arg, frozen) {
|
if (typeof arg !== 'undefined') {
|
return arg;
|
}
|
},
|
}
|
|
const optional = serial.assigned({
|
prepend: assignTruthful,
|
replaces: assignTruthful,
|
critical: assignTruthful,
|
namespaceObjectAsContext: assignDefined,
|
callArgs: assignDefined,
|
call: assignDefined,
|
directImport: assignDefined,
|
shorthand: assignDefined,
|
optional: assignTruthful,
|
loc: {
|
freeze(arg, dependency) {
|
return flattenPrototype(dependency.loc);
|
},
|
thaw(arg, frozen) {
|
return arg;
|
},
|
},
|
});
|
|
const localModuleAssigned = {
|
freeze(_, dependency) {
|
if (
|
typeof dependency.localModule === 'object' &&
|
dependency.localModule !== null
|
) {
|
return {
|
name: dependency.localModule.name,
|
idx: dependency.localModule.idx,
|
used: dependency.localModule.used,
|
};
|
}
|
},
|
thaw(thawed, localModule, extra) {
|
const state = extra.state;
|
if (
|
typeof localModule === 'object' &&
|
localModule !== null
|
) {
|
if (!state.localModules) {
|
state.localModules = [];
|
}
|
if (!state.localModules[localModule.idx]) {
|
state.localModules[localModule.idx] = new LocalModule(
|
extra.module,
|
localModule.name,
|
localModule.idx,
|
);
|
state.localModules[localModule.idx].used =
|
localModule.used;
|
}
|
thawed.localModule = state.localModules[localModule.idx];
|
}
|
return thawed;
|
},
|
};
|
|
const warnings = {
|
freeze(frozen, dependency) {
|
if (frozen && dependency.getWarnings) {
|
const warnings = dependency.getWarnings();
|
if (warnings && warnings.length) {
|
return warnings.map(
|
({ stack }) =>
|
stack.includes('\n at Object.freeze')
|
? stack.split('\n at Object.freeze')[0]
|
: stack.includes('\n at pluginCompat.tap')
|
? stack.split('\n at pluginCompat.tap')[0]
|
: stack.split('\n at Compiler.pluginCompat.tap')[0],
|
);
|
}
|
}
|
},
|
thaw(dependency, warnings) {
|
if (dependency && warnings && dependency.getWarnings) {
|
const frozenWarnings = warnings;
|
const _getWarnings = dependency.getWarnings;
|
dependency.getWarnings = function() {
|
const warnings = _getWarnings.call(this);
|
if (warnings && warnings.length) {
|
return warnings.map((warning, i) => {
|
const stack = warning.stack.split(
|
'\n at Compilation.reportDependencyErrorsAndWarnings',
|
)[1];
|
warning.stack = `${
|
frozenWarnings[i]
|
}\n at Compilation.reportDependencyErrorsAndWarnings${stack}`;
|
return warning;
|
});
|
}
|
return warnings;
|
};
|
}
|
return dependency;
|
},
|
};
|
**/
|
|
const constructorArguments = {
|
/** dependencies
|
dependencies: {
|
freeze(arg, dependency, extra, methods) {
|
return methods.mapFreeze('Dependency', null, arg, extra);
|
},
|
thaw(arg, frozen, extra, methods) {
|
return methods.mapThaw('Dependency', null, arg, extra);
|
},
|
},
|
**/
|
/** freeze dependencies
|
dependencies: methods.mapFreeze('Dependency', null, dependency.dependencies, extra),
|
**/
|
/** thaw dependencies
|
methods.mapThaw('Dependency', null, frozen.dependencies, extra),
|
**/
|
/** depsArray
|
depsArray: {
|
freeze(arg, dependency, extra, methods) {
|
return methods.mapFreeze('Dependency', null, arg, extra);
|
},
|
thaw(arg, frozen, extra, methods) {
|
return methods.mapThaw('Dependency', null, arg, extra);
|
},
|
},
|
**/
|
/** freeze depsArray
|
depsArray: methods.mapFreeze('Dependency', null, dependency.depsArray, extra),
|
**/
|
/** thaw depsArray
|
methods.mapThaw('Dependency', null, frozen.depsArray, extra),
|
**/
|
/** localModule
|
localModule: {
|
freeze({ name, idx }, dependency, extra, methods) {
|
return {
|
name: name,
|
idx: idx,
|
};
|
},
|
thaw({ idx, name, used }, frozen, extra, methods) {
|
const state = extra.state;
|
if (!state.localModules) {
|
state.localModules = [];
|
}
|
if (!state.localModules[idx]) {
|
state.localModules[idx] = new LocalModule(extra.module, name, idx);
|
state.localModules[idx].used = used;
|
}
|
return state.localModules[idx];
|
},
|
},
|
**/
|
/** freeze localModule
|
localModule: {
|
name: dependency.localModule.name,
|
name: dependency.localModule.idx,
|
},
|
**/
|
/** thaw prep localModule
|
if (!extra.state.localModules) {
|
extra.state.localModules = [];
|
}
|
if (!extra.state.localModules[frozen.localModule.idx]) {
|
extra.state.localModules[frozen.localModule.idx] = new LocalModule(extra.module, frozen.localModule.name, frozen.localModule.idx);
|
extra.state.localModules[frozen.localModule.idx].used = frozen.localModule.used;
|
}
|
**/
|
/** thaw localModule
|
extra.state.localModules[frozen.localModule.idx],
|
**/
|
/** regExp
|
regExp: {
|
freeze(arg, dependency, extra, methods) {
|
return arg ? arg.source : false;
|
},
|
thaw(arg, frozen, extra, methods) {
|
return arg ? new RegExp(arg) : arg;
|
},
|
},
|
**/
|
/** freeze regExp
|
regExp: dependency.regExp ? dependency.regExp.source : false,
|
**/
|
/** thaw regExp
|
frozen.regExp ? new RegExp(frozen.regExp) : frozen.regExp,
|
**/
|
/** request
|
request: {
|
freeze(arg, dependency, extra, methods) {
|
return relateContext.relateAbsoluteRequest(extra.module.context, arg);
|
},
|
thaw(arg, dependency, extra, methods) {
|
return arg;
|
// return relateContext.contextNormalRequest(extra.compilation.compiler, arg);
|
},
|
},
|
**/
|
/** freeze request
|
request: relateContext.relateAbsoluteRequest(extra.module.context, dependency.request),
|
**/
|
/** thaw request
|
frozen.request,
|
**/
|
/** userRequest
|
userRequest: {
|
freeze(arg, dependency, extra, methods) {
|
return relateContext.relateAbsoluteRequest(extra.module.context, arg);
|
},
|
thaw(arg, dependency, extra, methods) {
|
return arg;
|
// return relateContext.contextNormalRequest(extra.compilation.compiler, arg);
|
},
|
},
|
**/
|
/** freeze userRequest
|
userRequest: relateContext.relateAbsoluteRequest(extra.module.context, dependency.userRequest),
|
**/
|
/** thaw userRequest
|
frozen.userRequest,
|
**/
|
/** block
|
block: {
|
freeze(arg, dependency, extra, methods) {
|
// Dependency nested in a parent. Freezing the block is a loop.
|
if (arg.dependencies.includes(dependency)) {
|
return;
|
}
|
return methods.freeze('DependencyBlock', null, arg, extra);
|
},
|
thaw(arg, frozen, extra, methods) {
|
// Not having a block, means it needs to create a cycle and refer to its
|
// parent.
|
if (!arg) {
|
return extra.parent;
|
}
|
return methods.thaw('DependencyBlock', null, arg, extra);
|
},
|
},
|
**/
|
/** freeze block
|
block: !dependency.block.dependencies.includes(dependency) ?
|
methods.freeze('DependencyBlock', null, dependency.block, extra) :
|
undefined,
|
**/
|
/** thaw block
|
!frozen.block ? extra.parent : methods.thaw('DependencyBlock', null, frozen.block, extra),
|
**/
|
/** importDependency
|
importDependency: {
|
freeze(arg, dependency, extra, methods) {
|
return methods.freeze('Dependency', null, arg, extra);
|
},
|
thaw(arg, frozen, extra, methods) {
|
return methods.thaw('Dependency', null, arg, extra);
|
},
|
},
|
**/
|
/** freeze importDependency
|
importDependency: methods.freeze('Dependency', null, dependency.importDependency, extra),
|
**/
|
/** thaw importDependency
|
methods.thaw('Dependency', null, frozen.importDependency, extra),
|
**/
|
/** originModule
|
originModule: {
|
freeze(arg, dependency, extra, methods) {
|
// This will be in extra, generated or found during the process of thawing.
|
},
|
thaw(arg, frozen, extra, methods) {
|
return extra.module;
|
},
|
},
|
**/
|
/** freeze originModule
|
originModule: null,
|
**/
|
/** thaw originModule
|
extra.module,
|
**/
|
/** activeExports
|
activeExports: {
|
freeze(arg, dependency, extra, methods) {
|
return null;
|
},
|
thaw(arg, { name }, { state }, methods) {
|
state.activeExports = state.activeExports || new Set();
|
if (name) {
|
state.activeExports.add(name);
|
}
|
return state.activeExports;
|
},
|
},
|
**/
|
/** freeze activeExports
|
activeExports: null,
|
**/
|
/** thaw prep activeExports
|
extra.state.activeExports = extra.state.activeExports || new Set();
|
if (frozen.name) {
|
extra.state.activeExports.add(frozen.name);
|
}
|
**/
|
/** thaw activeExports
|
extra.state.activeExports,
|
**/
|
/** otherStarExports
|
otherStarExports: {
|
freeze(arg, dependency, extra, methods) {
|
if (arg) {
|
// This will be in extra, generated during the process of thawing.
|
return 'star';
|
}
|
return null;
|
},
|
thaw(arg, frozen, { state }, methods) {
|
if (arg === 'star') {
|
return state.otherStarExports || [];
|
}
|
return null;
|
},
|
},
|
**/
|
/** freeze otherStarExports
|
otherStarExports: dependency.otherStarExports ? 'star' : null,
|
**/
|
/** thaw otherStarExports
|
frozen.otherStarExports === 'star' ?
|
(extra.state.otherStarExports || []) :
|
null,
|
**/
|
/** options
|
options: {
|
freeze(arg, dependency, extra, methods) {
|
if (arg.regExp) {
|
return Object.assign({}, arg, {
|
regExp: arg.regExp.source,
|
});
|
}
|
return arg;
|
},
|
thaw(arg, frozen, extra, methods) {
|
if (arg.regExp) {
|
return Object.assign({}, arg, {
|
regExp: new RegExp(arg.regExp),
|
});
|
}
|
return arg;
|
},
|
},
|
**/
|
/** freeze options
|
options: dependency.options.regExp ?
|
Object.assign({}, dependency.options, {
|
regExp: dependency.options.regExp.source,
|
}) :
|
dependency.options,
|
**/
|
/** thaw options
|
frozen.options.regExp ?
|
Object.assign({}, frozen.options, {
|
regExp: new RegExp(frozen.options.regExp),
|
}) :
|
frozen.options,
|
**/
|
/** parserScope
|
parserScope: {
|
freeze(arg, dependencies, extra, methods) {
|
return;
|
},
|
thaw(arg, frozen, { state }, methods) {
|
state.harmonyParserScope = state.harmonyParserScope || {};
|
return state.harmonyParserScope;
|
},
|
},
|
**/
|
/** freeze parserScope
|
parserScope: null,
|
**/
|
/** thaw prep parserScope
|
extra.state.harmonyParserScope = extra.state.harmonyParserScope || {};
|
**/
|
/** thaw parserScope
|
extra.state.harmonyParserScope,
|
**/
|
};
|
|
/** importDependencyState
|
importDependency: {
|
freeze(frozen) {
|
return frozen;
|
},
|
thaw(thawed, frozen, extra) {
|
const state = extra.state;
|
const ref = frozen.range.toString();
|
if (state.imports[ref]) {
|
return state.imports[ref];
|
}
|
state.imports[ref] = thawed;
|
return thawed;
|
},
|
},
|
**/
|
|
/** exportImportedDependencyState
|
exportImportedDependency: {
|
freeze(frozen) {},
|
thaw(thawed, frozen, extra) {
|
if (thawed.otherStarExports) {
|
extra.state.otherStarExports = (
|
extra.state.otherStarExports || []
|
).concat(thawed);
|
}
|
return thawed;
|
},
|
},
|
**/
|
|
const fs = require('graceful-fs');
|
const path = require('path');
|
|
const generateRaw = fs.readFileSync(path.join(__dirname, '_generate.js'), 'utf8');
|
const generateBlocks = generateRaw
|
.split(/((?:\/\*\*)((?!\*\*\/)[^\r\n]*\r?\n)+)/g)
|
.filter(Boolean)
|
.filter(str => !str.startsWith('**/'))
|
.reduce((carry, item, index) => index % 2 === 0 ? [...carry, item] : carry, []);
|
|
const getBlock = name => {
|
let lines = generateBlocks
|
.find(block => block.startsWith(`/** ${name}`));
|
if (lines) {
|
lines = lines.split('\n');
|
lines = lines.slice(1, lines.length - 1);
|
}
|
return lines || [];
|
};
|
|
const dependencyInfo = require('./basic-dependency.json');
|
|
let output = getBlock('prelude');
|
|
for (const dependency of dependencyInfo) {
|
const DepName = dependency[0];
|
const depName = DepName[0].toLowerCase() + DepName.slice(1);
|
const DepNameSerial = `${DepName}Serial`;
|
output.push(`const ${dependency[0]} = require('webpack/lib/dependencies/${dependency[0]}');`);
|
output.push(`const ${DepNameSerial} = serial.serial('${DepName}', {`);
|
|
// output.push(` constructor: serial.constructed(${DepName}, {`);
|
// for (const argument of dependency.slice(1)) {
|
// let block = getBlock(argument);
|
// if (!block.length) {
|
// block = [` ${argument}: serial.identity,`];
|
// }
|
// output.push(...block);
|
// }
|
// output.push(` }),`);
|
|
output.push(` constructor: {`);
|
output.push(` freeze(_, dependency, extra, methods) {`);
|
output.push(` return {`);
|
for (const argument of dependency.slice(1)) {
|
let block = getBlock(`freeze ${argument}`);
|
if (!block.length) {
|
block = [` ${argument}: dependency.${argument},`];
|
}
|
output.push(...block);
|
}
|
output.push(` };`);
|
output.push(` },`);
|
output.push(` thaw(thawed, frozen, extra, methods) {`);
|
for (const argument of dependency.slice(1)) {
|
let block = getBlock(`thaw prep ${argument}`);
|
output.push(...block);
|
}
|
output.push(` return new ${DepName}(`);
|
for (const argument of dependency.slice(1)) {
|
let block = getBlock(`thaw ${argument}`);
|
if (!block.length) {
|
block = [` frozen.${argument},`];
|
}
|
output.push(...block);
|
}
|
output.push(` );`);
|
output.push(` },`);
|
output.push(` },`);
|
|
output.push(``);
|
output.push(` optional,`);
|
|
if (DepName === 'AMDDefineDependency' || DepName === 'LocalModuleDependency') {
|
output.push(``);
|
output.push(` localModuleAssigned,`);
|
}
|
|
output.push(``);
|
output.push(` warnings,`);
|
|
if (DepName === 'HarmonyImportDependency') {
|
output.push(``);
|
output.push(...getBlock('importDependencyState'));
|
}
|
|
if (DepName === 'HarmonyExportImportedSpecifierDependency') {
|
output.push(``);
|
output.push(...getBlock('exportImportedDependencyState'));
|
}
|
|
output.push(`});`);
|
output.push(``);
|
}
|
|
output.push(`exports.map = new Map();`);
|
for (const dependency of dependencyInfo) {
|
const DepName = dependency[0];
|
const DepNameSerial = `${DepName}Serial`;
|
output.push(`exports.${DepName} = ${DepNameSerial};`);
|
output.push(`exports.map.set(${DepName}, ${DepNameSerial});`);
|
}
|
output.push(``);
|
|
require('graceful-fs').writeFileSync(require('path').join(__dirname, 'index.js'), output.join('\n'), 'utf8');
|