TransformSourcePlugin.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. const relateContext = require('./util/relate-context');
  2. const pluginCompat = require('./util/plugin-compat');
  3. const SourceSchemas3 = [
  4. ['CachedSource', 'source'],
  5. ['ConcatSource'],
  6. ['LineToLineMappedSource', 'value', 'name', 'originalSource'],
  7. ['OriginalSource', 'value', 'name'],
  8. ['RawSource', 'value'],
  9. ['ReplaceSource', 'source', 'name'],
  10. [
  11. 'SourceMapSource',
  12. 'value',
  13. 'name',
  14. 'sourceMap',
  15. 'originalSource',
  16. 'innerSourceMap',
  17. ],
  18. ];
  19. try {
  20. SourceSchemas3[0].Source = require('webpack-sources/lib/CachedSource');
  21. } catch (_) {}
  22. try {
  23. SourceSchemas3[1].Source = require('webpack-sources/lib/ConcatSource');
  24. } catch (_) {}
  25. try {
  26. SourceSchemas3[2].Source = require('webpack-sources/lib/LineToLineMappedSource');
  27. } catch (_) {}
  28. try {
  29. SourceSchemas3[3].Source = require('webpack-sources/lib/OriginalSource');
  30. } catch (_) {}
  31. try {
  32. SourceSchemas3[4].Source = require('webpack-sources/lib/RawSource');
  33. } catch (_) {}
  34. try {
  35. SourceSchemas3[5].Source = require('webpack-sources/lib/ReplaceSource');
  36. } catch (_) {}
  37. try {
  38. SourceSchemas3[6].Source = require('webpack-sources/lib/SourceMapSource');
  39. } catch (_) {}
  40. const freezeArgument = {
  41. value(arg, { _value }, extra, methods) {
  42. return _value;
  43. },
  44. name(arg, { _name }, { compilation }, methods) {
  45. try {
  46. return relateContext.relateNormalPath(compilation.compiler, _name);
  47. } catch (e) {
  48. console.error(e.stack);
  49. process.exit();
  50. }
  51. },
  52. sourceMap(arg, { _sourceMap }, extra, methods) {
  53. return _sourceMap;
  54. },
  55. originalSource(arg, { _originalSource }, extra, methods) {
  56. return _originalSource;
  57. },
  58. innerSourceMap(arg, { _innerSourceMap }, extra, methods) {
  59. return _innerSourceMap;
  60. },
  61. source(arg, { constructor, _source }, extra, methods) {
  62. if (constructor.name === 'ReplaceSource') {
  63. return;
  64. }
  65. return methods.freeze('Source', null, _source, extra);
  66. },
  67. };
  68. const thawArgument = {
  69. name(arg, source, { compilation }, methods) {
  70. try {
  71. return relateContext.contextNormalPath(compilation.compiler, arg);
  72. } catch (e) {
  73. console.error(e.stack);
  74. process.exit();
  75. }
  76. },
  77. source(arg, { type }, extra, methods) {
  78. if (type === 'ReplaceSource') {
  79. return extra.source;
  80. }
  81. return methods.thaw('Source', null, arg, extra);
  82. },
  83. value(arg, frozen, extra, methods) {
  84. if (arg && arg.type === 'Buffer') {
  85. return new Buffer(arg.data);
  86. }
  87. return arg;
  88. },
  89. };
  90. function freezeSource(source, extra, methods) {
  91. const schemas = extra.schemas;
  92. for (let i = 0; i < schemas.length; i++) {
  93. if (source.constructor.name === schemas[i].Source.name) {
  94. const frozen = {
  95. type: schemas[i][0],
  96. };
  97. for (let j = 1; j < schemas[i].length; j++) {
  98. let arg = source[schemas[i][j]];
  99. if (freezeArgument[schemas[i][j]]) {
  100. arg = freezeArgument[schemas[i][j]](arg, source, extra, methods);
  101. }
  102. frozen[schemas[i][j]] = arg;
  103. }
  104. return frozen;
  105. }
  106. }
  107. throw new Error(`Unfrozen ${source.constructor.name}.`);
  108. }
  109. function thawSource(frozen, extra, methods) {
  110. const schemas = extra.schemas;
  111. for (let i = 0; i < schemas.length; i++) {
  112. if (frozen.type === schemas[i][0]) {
  113. const Source = schemas[i].Source;
  114. const args = [];
  115. for (let j = 1; j < schemas[i].length; j++) {
  116. let arg = frozen[schemas[i][j]];
  117. if (thawArgument[schemas[i][j]]) {
  118. arg = thawArgument[schemas[i][j]](arg, frozen, extra, methods);
  119. }
  120. args.push(arg);
  121. }
  122. try {
  123. return new Source(...args);
  124. } catch (_) {
  125. return new (Function.prototype.bind.apply(
  126. Source,
  127. [null].concat(args),
  128. ))();
  129. }
  130. }
  131. }
  132. }
  133. class TransformSourcePlugin {
  134. apply(compiler) {
  135. let methods;
  136. pluginCompat.tap(
  137. compiler,
  138. '_hardSourceMethods',
  139. 'TransformSourcePlugin',
  140. _methods => {
  141. methods = _methods;
  142. },
  143. );
  144. pluginCompat.tap(
  145. compiler,
  146. '_hardSourceFreezeSource',
  147. 'TransformSourcePlugin freeze',
  148. (frozen, source, extra) => {
  149. if (typeof source === 'string') {
  150. return {
  151. type: 'String',
  152. value: source,
  153. };
  154. } else if (Buffer.isBuffer && Buffer.isBuffer(source)) {
  155. // Serialization layer might transform it into JSON or handle it as binary
  156. // data
  157. return source;
  158. }
  159. extra.schemas = SourceSchemas3;
  160. frozen = freezeSource(source, extra, methods);
  161. if (frozen.type === 'ReplaceSource') {
  162. frozen.replacements = source.replacements;
  163. } else if (frozen.type === 'CachedSource') {
  164. frozen.cachedSource = source._cachedSource;
  165. frozen.cachedSize = source._cachedSize;
  166. frozen.cachedMaps = source._cachedMaps;
  167. } else if (frozen.type === 'ConcatSource') {
  168. frozen.children = methods.mapFreeze(
  169. 'Source',
  170. null,
  171. source.children,
  172. extra,
  173. );
  174. }
  175. return frozen;
  176. },
  177. );
  178. pluginCompat.tap(
  179. compiler,
  180. '_hardSourceThawSource',
  181. 'TransformSourcePlugin thaw',
  182. (source, frozen, extra) => {
  183. if (frozen.type === 'String') {
  184. return frozen.value;
  185. } else if (frozen.type === 'Buffer') {
  186. return new Buffer(frozen.data);
  187. } else if (Buffer.isBuffer && Buffer.isBuffer(frozen)) {
  188. return frozen;
  189. }
  190. extra.schemas = SourceSchemas3;
  191. source = thawSource(frozen, extra, methods);
  192. if (frozen.type === 'ReplaceSource') {
  193. source.replacements = frozen.replacements;
  194. } else if (frozen.type === 'CachedSource') {
  195. source._cachedSource = frozen.cachedSource;
  196. source._cachedSize = frozen.cachedSize;
  197. source._cachedMaps = frozen.cachedMaps;
  198. } else if (frozen.type === 'ConcatSource') {
  199. source.children = methods.mapThaw(
  200. 'Source',
  201. null,
  202. frozen.children,
  203. extra,
  204. );
  205. }
  206. return source;
  207. },
  208. );
  209. }
  210. }
  211. module.exports = TransformSourcePlugin;