AlipayEventSourceFixPlugin.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. const fs = require('fs');
  2. const path = require('path');
  3. class AlipayEventSourceFixPlugin {
  4. apply(compiler) {
  5. // 在构建完成后执行
  6. compiler.hooks.afterEmit.tapAsync('AlipayEventSourceFixPlugin', (compilation, callback) => {
  7. this.fixEventSource();
  8. callback();
  9. });
  10. }
  11. fixEventSource() {
  12. const taroJsPath = path.join(process.cwd(), 'dist', 'taro.js');
  13. if (!fs.existsSync(taroJsPath)) {
  14. console.log('AlipayEventSourceFixPlugin: dist/taro.js not found');
  15. return;
  16. }
  17. console.log('AlipayEventSourceFixPlugin: Fixing EventSource in dist/taro.js...');
  18. let content = fs.readFileSync(taroJsPath, 'utf8');
  19. // 检查是否存在EventSource相关的代码
  20. if (content.includes('EventSource')) {
  21. console.log('AlipayEventSourceFixPlugin: Found EventSource in dist/taro.js');
  22. // 新的EventSource实现(使用标准格式,确保语法正确)
  23. const newEventSource = 'class EventSource {\n data = {};\n\n get(id) {\n return this.data[id];\n }\n\n set(id, value) {\n this.data[id] = value;\n }\n\n delete(id) {\n delete this.data[id];\n }\n\n has(id) {\n return id in this.data;\n }\n\n removeNode(child) {\n const { sid, uid } = child;\n this.delete(sid);\n if (uid !== sid && uid) this.delete(uid);\n }\n\n removeNodeTree(child) {\n this.removeNode(child);\n const { childNodes } = child;\n childNodes.forEach((node) => this.removeNodeTree(node));\n }\n}';
  24. let replaced = false;
  25. // 方式1:查找并替换event-source.js模块
  26. const eventSourceModulePattern = /\/\*\*\*\.\/node_modules\/@tarojs\/runtime\/dist\/dom\/event-source\.js[\s\S]*?class EventSource[\s\S]*?\/\*\*\*\/\s*\}\);/g;
  27. if (eventSourceModulePattern.test(content)) {
  28. console.log('AlipayEventSourceFixPlugin: Found event-source.js module');
  29. const matches = content.match(eventSourceModulePattern);
  30. if (matches && matches.length > 0) {
  31. const oldModule = matches[0];
  32. // 提取模块的开头部分
  33. const moduleStart = oldModule.substring(0, oldModule.indexOf('class EventSource'));
  34. // 提取模块的结尾部分
  35. const moduleEnd = oldModule.substring(oldModule.lastIndexOf('*/') + 2);
  36. // 构建新的模块内容
  37. const newModule = moduleStart + newEventSource + moduleEnd;
  38. // 替换整个模块
  39. content = content.replace(oldModule, newModule);
  40. fs.writeFileSync(taroJsPath, content, 'utf8');
  41. console.log('AlipayEventSourceFixPlugin: Success: EventSource module replaced');
  42. replaced = true;
  43. }
  44. }
  45. // 方式2:直接查找EventSource类定义
  46. if (!replaced) {
  47. const eventSourceStart = content.indexOf('class EventSource');
  48. if (eventSourceStart !== -1) {
  49. console.log('AlipayEventSourceFixPlugin: Found EventSource class');
  50. // 查找类的结束位置
  51. let braceCount = 0;
  52. let eventSourceEnd = eventSourceStart;
  53. let foundOpeningBrace = false;
  54. for (let i = eventSourceStart; i < content.length; i++) {
  55. if (content[i] === '{') {
  56. braceCount++;
  57. foundOpeningBrace = true;
  58. } else if (content[i] === '}') {
  59. braceCount--;
  60. if (foundOpeningBrace && braceCount === 0) {
  61. eventSourceEnd = i + 1; // 包含结束大括号
  62. break;
  63. }
  64. }
  65. }
  66. if (eventSourceEnd > eventSourceStart) {
  67. const oldEventSource = content.substring(eventSourceStart, eventSourceEnd);
  68. // 替换为新的实现
  69. content = content.replace(oldEventSource, newEventSource);
  70. fs.writeFileSync(taroJsPath, content, 'utf8');
  71. console.log('AlipayEventSourceFixPlugin: Success: EventSource class replaced');
  72. replaced = true;
  73. }
  74. }
  75. }
  76. // 方式3:处理压缩后的EventSource类
  77. if (!replaced) {
  78. const compressedPattern = /class EventSource[^{]*\{[^}]*\{[^}]*\{[^}]*\}[^}]*\}[^}]*\}/g;
  79. if (compressedPattern.test(content)) {
  80. console.log('AlipayEventSourceFixPlugin: Found compressed EventSource');
  81. const matches = content.match(compressedPattern);
  82. if (matches && matches.length > 0) {
  83. content = content.replace(matches[0], newEventSource);
  84. fs.writeFileSync(taroJsPath, content, 'utf8');
  85. console.log('AlipayEventSourceFixPlugin: Success: Compressed EventSource replaced');
  86. replaced = true;
  87. }
  88. }
  89. }
  90. // 方式4:处理语法错误的情况
  91. if (!replaced && content.includes('class EventSource') && (content.includes('sid, uid') || content.includes('childNodes'))) {
  92. console.log('AlipayEventSourceFixPlugin: Found EventSource with potential syntax errors');
  93. // 查找EventSource开始位置
  94. const eventSourceStart = content.indexOf('class EventSource');
  95. if (eventSourceStart !== -1) {
  96. // 查找一个合理的结束位置
  97. const eventSourceEnd = content.indexOf('eventSource', eventSourceStart);
  98. if (eventSourceEnd > eventSourceStart) {
  99. // 提取从EventSource开始到eventSource变量定义之间的内容
  100. const oldEventSource = content.substring(eventSourceStart, eventSourceEnd);
  101. // 替换为新的实现
  102. content = content.replace(oldEventSource, newEventSource);
  103. fs.writeFileSync(taroJsPath, content, 'utf8');
  104. console.log('AlipayEventSourceFixPlugin: Success: EventSource with syntax errors fixed');
  105. replaced = true;
  106. }
  107. }
  108. }
  109. if (!replaced) {
  110. console.log('AlipayEventSourceFixPlugin: Info: EventSource not found or could not be replaced');
  111. }
  112. } else {
  113. console.log('AlipayEventSourceFixPlugin: Info: No EventSource found in dist/taro.js');
  114. }
  115. }
  116. }
  117. module.exports = AlipayEventSourceFixPlugin;