_generate.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561
  1. /** prelude
  2. const serial = require('../util/serial');
  3. const relateContext = require('../util/relate-context');
  4. const LocalModule = require('webpack/lib/dependencies/LocalModule');
  5. function flattenPrototype(obj) {
  6. if (typeof obj === 'string') {
  7. return obj;
  8. }
  9. const copy = {};
  10. for (const key in obj) {
  11. copy[key] = obj[key];
  12. }
  13. return copy;
  14. }
  15. const assignTruthful = {
  16. freeze(arg, dependency) {
  17. return arg;
  18. },
  19. thaw(arg, frozen) {
  20. return arg;
  21. },
  22. };
  23. const assignDefined = {
  24. freeze(arg, dependency) {
  25. if (typeof arg !== 'undefined') {
  26. return arg;
  27. }
  28. },
  29. thaw(arg, frozen) {
  30. if (typeof arg !== 'undefined') {
  31. return arg;
  32. }
  33. },
  34. }
  35. const optional = serial.assigned({
  36. prepend: assignTruthful,
  37. replaces: assignTruthful,
  38. critical: assignTruthful,
  39. namespaceObjectAsContext: assignDefined,
  40. callArgs: assignDefined,
  41. call: assignDefined,
  42. directImport: assignDefined,
  43. shorthand: assignDefined,
  44. optional: assignTruthful,
  45. loc: {
  46. freeze(arg, dependency) {
  47. return flattenPrototype(dependency.loc);
  48. },
  49. thaw(arg, frozen) {
  50. return arg;
  51. },
  52. },
  53. });
  54. const localModuleAssigned = {
  55. freeze(_, dependency) {
  56. if (
  57. typeof dependency.localModule === 'object' &&
  58. dependency.localModule !== null
  59. ) {
  60. return {
  61. name: dependency.localModule.name,
  62. idx: dependency.localModule.idx,
  63. used: dependency.localModule.used,
  64. };
  65. }
  66. },
  67. thaw(thawed, localModule, extra) {
  68. const state = extra.state;
  69. if (
  70. typeof localModule === 'object' &&
  71. localModule !== null
  72. ) {
  73. if (!state.localModules) {
  74. state.localModules = [];
  75. }
  76. if (!state.localModules[localModule.idx]) {
  77. state.localModules[localModule.idx] = new LocalModule(
  78. extra.module,
  79. localModule.name,
  80. localModule.idx,
  81. );
  82. state.localModules[localModule.idx].used =
  83. localModule.used;
  84. }
  85. thawed.localModule = state.localModules[localModule.idx];
  86. }
  87. return thawed;
  88. },
  89. };
  90. const warnings = {
  91. freeze(frozen, dependency) {
  92. if (frozen && dependency.getWarnings) {
  93. const warnings = dependency.getWarnings();
  94. if (warnings && warnings.length) {
  95. return warnings.map(
  96. ({ stack }) =>
  97. stack.includes('\n at Object.freeze')
  98. ? stack.split('\n at Object.freeze')[0]
  99. : stack.includes('\n at pluginCompat.tap')
  100. ? stack.split('\n at pluginCompat.tap')[0]
  101. : stack.split('\n at Compiler.pluginCompat.tap')[0],
  102. );
  103. }
  104. }
  105. },
  106. thaw(dependency, warnings) {
  107. if (dependency && warnings && dependency.getWarnings) {
  108. const frozenWarnings = warnings;
  109. const _getWarnings = dependency.getWarnings;
  110. dependency.getWarnings = function() {
  111. const warnings = _getWarnings.call(this);
  112. if (warnings && warnings.length) {
  113. return warnings.map((warning, i) => {
  114. const stack = warning.stack.split(
  115. '\n at Compilation.reportDependencyErrorsAndWarnings',
  116. )[1];
  117. warning.stack = `${
  118. frozenWarnings[i]
  119. }\n at Compilation.reportDependencyErrorsAndWarnings${stack}`;
  120. return warning;
  121. });
  122. }
  123. return warnings;
  124. };
  125. }
  126. return dependency;
  127. },
  128. };
  129. **/
  130. const constructorArguments = {
  131. /** dependencies
  132. dependencies: {
  133. freeze(arg, dependency, extra, methods) {
  134. return methods.mapFreeze('Dependency', null, arg, extra);
  135. },
  136. thaw(arg, frozen, extra, methods) {
  137. return methods.mapThaw('Dependency', null, arg, extra);
  138. },
  139. },
  140. **/
  141. /** freeze dependencies
  142. dependencies: methods.mapFreeze('Dependency', null, dependency.dependencies, extra),
  143. **/
  144. /** thaw dependencies
  145. methods.mapThaw('Dependency', null, frozen.dependencies, extra),
  146. **/
  147. /** depsArray
  148. depsArray: {
  149. freeze(arg, dependency, extra, methods) {
  150. return methods.mapFreeze('Dependency', null, arg, extra);
  151. },
  152. thaw(arg, frozen, extra, methods) {
  153. return methods.mapThaw('Dependency', null, arg, extra);
  154. },
  155. },
  156. **/
  157. /** freeze depsArray
  158. depsArray: methods.mapFreeze('Dependency', null, dependency.depsArray, extra),
  159. **/
  160. /** thaw depsArray
  161. methods.mapThaw('Dependency', null, frozen.depsArray, extra),
  162. **/
  163. /** localModule
  164. localModule: {
  165. freeze({ name, idx }, dependency, extra, methods) {
  166. return {
  167. name: name,
  168. idx: idx,
  169. };
  170. },
  171. thaw({ idx, name, used }, frozen, extra, methods) {
  172. const state = extra.state;
  173. if (!state.localModules) {
  174. state.localModules = [];
  175. }
  176. if (!state.localModules[idx]) {
  177. state.localModules[idx] = new LocalModule(extra.module, name, idx);
  178. state.localModules[idx].used = used;
  179. }
  180. return state.localModules[idx];
  181. },
  182. },
  183. **/
  184. /** freeze localModule
  185. localModule: {
  186. name: dependency.localModule.name,
  187. name: dependency.localModule.idx,
  188. },
  189. **/
  190. /** thaw prep localModule
  191. if (!extra.state.localModules) {
  192. extra.state.localModules = [];
  193. }
  194. if (!extra.state.localModules[frozen.localModule.idx]) {
  195. extra.state.localModules[frozen.localModule.idx] = new LocalModule(extra.module, frozen.localModule.name, frozen.localModule.idx);
  196. extra.state.localModules[frozen.localModule.idx].used = frozen.localModule.used;
  197. }
  198. **/
  199. /** thaw localModule
  200. extra.state.localModules[frozen.localModule.idx],
  201. **/
  202. /** regExp
  203. regExp: {
  204. freeze(arg, dependency, extra, methods) {
  205. return arg ? arg.source : false;
  206. },
  207. thaw(arg, frozen, extra, methods) {
  208. return arg ? new RegExp(arg) : arg;
  209. },
  210. },
  211. **/
  212. /** freeze regExp
  213. regExp: dependency.regExp ? dependency.regExp.source : false,
  214. **/
  215. /** thaw regExp
  216. frozen.regExp ? new RegExp(frozen.regExp) : frozen.regExp,
  217. **/
  218. /** request
  219. request: {
  220. freeze(arg, dependency, extra, methods) {
  221. return relateContext.relateAbsoluteRequest(extra.module.context, arg);
  222. },
  223. thaw(arg, dependency, extra, methods) {
  224. return arg;
  225. // return relateContext.contextNormalRequest(extra.compilation.compiler, arg);
  226. },
  227. },
  228. **/
  229. /** freeze request
  230. request: relateContext.relateAbsoluteRequest(extra.module.context, dependency.request),
  231. **/
  232. /** thaw request
  233. frozen.request,
  234. **/
  235. /** userRequest
  236. userRequest: {
  237. freeze(arg, dependency, extra, methods) {
  238. return relateContext.relateAbsoluteRequest(extra.module.context, arg);
  239. },
  240. thaw(arg, dependency, extra, methods) {
  241. return arg;
  242. // return relateContext.contextNormalRequest(extra.compilation.compiler, arg);
  243. },
  244. },
  245. **/
  246. /** freeze userRequest
  247. userRequest: relateContext.relateAbsoluteRequest(extra.module.context, dependency.userRequest),
  248. **/
  249. /** thaw userRequest
  250. frozen.userRequest,
  251. **/
  252. /** block
  253. block: {
  254. freeze(arg, dependency, extra, methods) {
  255. // Dependency nested in a parent. Freezing the block is a loop.
  256. if (arg.dependencies.includes(dependency)) {
  257. return;
  258. }
  259. return methods.freeze('DependencyBlock', null, arg, extra);
  260. },
  261. thaw(arg, frozen, extra, methods) {
  262. // Not having a block, means it needs to create a cycle and refer to its
  263. // parent.
  264. if (!arg) {
  265. return extra.parent;
  266. }
  267. return methods.thaw('DependencyBlock', null, arg, extra);
  268. },
  269. },
  270. **/
  271. /** freeze block
  272. block: !dependency.block.dependencies.includes(dependency) ?
  273. methods.freeze('DependencyBlock', null, dependency.block, extra) :
  274. undefined,
  275. **/
  276. /** thaw block
  277. !frozen.block ? extra.parent : methods.thaw('DependencyBlock', null, frozen.block, extra),
  278. **/
  279. /** importDependency
  280. importDependency: {
  281. freeze(arg, dependency, extra, methods) {
  282. return methods.freeze('Dependency', null, arg, extra);
  283. },
  284. thaw(arg, frozen, extra, methods) {
  285. return methods.thaw('Dependency', null, arg, extra);
  286. },
  287. },
  288. **/
  289. /** freeze importDependency
  290. importDependency: methods.freeze('Dependency', null, dependency.importDependency, extra),
  291. **/
  292. /** thaw importDependency
  293. methods.thaw('Dependency', null, frozen.importDependency, extra),
  294. **/
  295. /** originModule
  296. originModule: {
  297. freeze(arg, dependency, extra, methods) {
  298. // This will be in extra, generated or found during the process of thawing.
  299. },
  300. thaw(arg, frozen, extra, methods) {
  301. return extra.module;
  302. },
  303. },
  304. **/
  305. /** freeze originModule
  306. originModule: null,
  307. **/
  308. /** thaw originModule
  309. extra.module,
  310. **/
  311. /** activeExports
  312. activeExports: {
  313. freeze(arg, dependency, extra, methods) {
  314. return null;
  315. },
  316. thaw(arg, { name }, { state }, methods) {
  317. state.activeExports = state.activeExports || new Set();
  318. if (name) {
  319. state.activeExports.add(name);
  320. }
  321. return state.activeExports;
  322. },
  323. },
  324. **/
  325. /** freeze activeExports
  326. activeExports: null,
  327. **/
  328. /** thaw prep activeExports
  329. extra.state.activeExports = extra.state.activeExports || new Set();
  330. if (frozen.name) {
  331. extra.state.activeExports.add(frozen.name);
  332. }
  333. **/
  334. /** thaw activeExports
  335. extra.state.activeExports,
  336. **/
  337. /** otherStarExports
  338. otherStarExports: {
  339. freeze(arg, dependency, extra, methods) {
  340. if (arg) {
  341. // This will be in extra, generated during the process of thawing.
  342. return 'star';
  343. }
  344. return null;
  345. },
  346. thaw(arg, frozen, { state }, methods) {
  347. if (arg === 'star') {
  348. return state.otherStarExports || [];
  349. }
  350. return null;
  351. },
  352. },
  353. **/
  354. /** freeze otherStarExports
  355. otherStarExports: dependency.otherStarExports ? 'star' : null,
  356. **/
  357. /** thaw otherStarExports
  358. frozen.otherStarExports === 'star' ?
  359. (extra.state.otherStarExports || []) :
  360. null,
  361. **/
  362. /** options
  363. options: {
  364. freeze(arg, dependency, extra, methods) {
  365. if (arg.regExp) {
  366. return Object.assign({}, arg, {
  367. regExp: arg.regExp.source,
  368. });
  369. }
  370. return arg;
  371. },
  372. thaw(arg, frozen, extra, methods) {
  373. if (arg.regExp) {
  374. return Object.assign({}, arg, {
  375. regExp: new RegExp(arg.regExp),
  376. });
  377. }
  378. return arg;
  379. },
  380. },
  381. **/
  382. /** freeze options
  383. options: dependency.options.regExp ?
  384. Object.assign({}, dependency.options, {
  385. regExp: dependency.options.regExp.source,
  386. }) :
  387. dependency.options,
  388. **/
  389. /** thaw options
  390. frozen.options.regExp ?
  391. Object.assign({}, frozen.options, {
  392. regExp: new RegExp(frozen.options.regExp),
  393. }) :
  394. frozen.options,
  395. **/
  396. /** parserScope
  397. parserScope: {
  398. freeze(arg, dependencies, extra, methods) {
  399. return;
  400. },
  401. thaw(arg, frozen, { state }, methods) {
  402. state.harmonyParserScope = state.harmonyParserScope || {};
  403. return state.harmonyParserScope;
  404. },
  405. },
  406. **/
  407. /** freeze parserScope
  408. parserScope: null,
  409. **/
  410. /** thaw prep parserScope
  411. extra.state.harmonyParserScope = extra.state.harmonyParserScope || {};
  412. **/
  413. /** thaw parserScope
  414. extra.state.harmonyParserScope,
  415. **/
  416. };
  417. /** importDependencyState
  418. importDependency: {
  419. freeze(frozen) {
  420. return frozen;
  421. },
  422. thaw(thawed, frozen, extra) {
  423. const state = extra.state;
  424. const ref = frozen.range.toString();
  425. if (state.imports[ref]) {
  426. return state.imports[ref];
  427. }
  428. state.imports[ref] = thawed;
  429. return thawed;
  430. },
  431. },
  432. **/
  433. /** exportImportedDependencyState
  434. exportImportedDependency: {
  435. freeze(frozen) {},
  436. thaw(thawed, frozen, extra) {
  437. if (thawed.otherStarExports) {
  438. extra.state.otherStarExports = (
  439. extra.state.otherStarExports || []
  440. ).concat(thawed);
  441. }
  442. return thawed;
  443. },
  444. },
  445. **/
  446. const fs = require('graceful-fs');
  447. const path = require('path');
  448. const generateRaw = fs.readFileSync(path.join(__dirname, '_generate.js'), 'utf8');
  449. const generateBlocks = generateRaw
  450. .split(/((?:\/\*\*)((?!\*\*\/)[^\r\n]*\r?\n)+)/g)
  451. .filter(Boolean)
  452. .filter(str => !str.startsWith('**/'))
  453. .reduce((carry, item, index) => index % 2 === 0 ? [...carry, item] : carry, []);
  454. const getBlock = name => {
  455. let lines = generateBlocks
  456. .find(block => block.startsWith(`/** ${name}`));
  457. if (lines) {
  458. lines = lines.split('\n');
  459. lines = lines.slice(1, lines.length - 1);
  460. }
  461. return lines || [];
  462. };
  463. const dependencyInfo = require('./basic-dependency.json');
  464. let output = getBlock('prelude');
  465. for (const dependency of dependencyInfo) {
  466. const DepName = dependency[0];
  467. const depName = DepName[0].toLowerCase() + DepName.slice(1);
  468. const DepNameSerial = `${DepName}Serial`;
  469. output.push(`const ${dependency[0]} = require('webpack/lib/dependencies/${dependency[0]}');`);
  470. output.push(`const ${DepNameSerial} = serial.serial('${DepName}', {`);
  471. // output.push(` constructor: serial.constructed(${DepName}, {`);
  472. // for (const argument of dependency.slice(1)) {
  473. // let block = getBlock(argument);
  474. // if (!block.length) {
  475. // block = [` ${argument}: serial.identity,`];
  476. // }
  477. // output.push(...block);
  478. // }
  479. // output.push(` }),`);
  480. output.push(` constructor: {`);
  481. output.push(` freeze(_, dependency, extra, methods) {`);
  482. output.push(` return {`);
  483. for (const argument of dependency.slice(1)) {
  484. let block = getBlock(`freeze ${argument}`);
  485. if (!block.length) {
  486. block = [` ${argument}: dependency.${argument},`];
  487. }
  488. output.push(...block);
  489. }
  490. output.push(` };`);
  491. output.push(` },`);
  492. output.push(` thaw(thawed, frozen, extra, methods) {`);
  493. for (const argument of dependency.slice(1)) {
  494. let block = getBlock(`thaw prep ${argument}`);
  495. output.push(...block);
  496. }
  497. output.push(` return new ${DepName}(`);
  498. for (const argument of dependency.slice(1)) {
  499. let block = getBlock(`thaw ${argument}`);
  500. if (!block.length) {
  501. block = [` frozen.${argument},`];
  502. }
  503. output.push(...block);
  504. }
  505. output.push(` );`);
  506. output.push(` },`);
  507. output.push(` },`);
  508. output.push(``);
  509. output.push(` optional,`);
  510. if (DepName === 'AMDDefineDependency' || DepName === 'LocalModuleDependency') {
  511. output.push(``);
  512. output.push(` localModuleAssigned,`);
  513. }
  514. output.push(``);
  515. output.push(` warnings,`);
  516. if (DepName === 'HarmonyImportDependency') {
  517. output.push(``);
  518. output.push(...getBlock('importDependencyState'));
  519. }
  520. if (DepName === 'HarmonyExportImportedSpecifierDependency') {
  521. output.push(``);
  522. output.push(...getBlock('exportImportedDependencyState'));
  523. }
  524. output.push(`});`);
  525. output.push(``);
  526. }
  527. output.push(`exports.map = new Map();`);
  528. for (const dependency of dependencyInfo) {
  529. const DepName = dependency[0];
  530. const DepNameSerial = `${DepName}Serial`;
  531. output.push(`exports.${DepName} = ${DepNameSerial};`);
  532. output.push(`exports.map.set(${DepName}, ${DepNameSerial});`);
  533. }
  534. output.push(``);
  535. require('graceful-fs').writeFileSync(require('path').join(__dirname, 'index.js'), output.join('\n'), 'utf8');