@kezh/my-custom-js-converter 1.10.0 → 1.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/encode/index.js +43 -5
- package/core/util/ast.js +32 -2
- package/package.json +1 -1
package/core/encode/index.js
CHANGED
|
@@ -119,16 +119,23 @@ function reorderMethods(methods) {
|
|
|
119
119
|
}
|
|
120
120
|
/**
|
|
121
121
|
* 防护检测:源文件 mount 对象内若残留 `__mod` 后缀方法,且同时通过 require 引入了
|
|
122
|
-
*
|
|
122
|
+
* 工具方法依赖,则按场景区分处理:
|
|
123
123
|
*
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
124
|
+
* 场景 A(真篡改风险):`__mod` 后缀方法对应的 mod 名能在 libs 目录找到独立模块文件。
|
|
125
|
+
* 说明用户复用了 decode 产物(含未还原的 `validate__util` 等内联 lib 方法)作为二开源文件,
|
|
126
|
+
* 同时又保留了 `const util = require(...)`。此时若继续 encode,会导致方法重复定义、
|
|
127
|
+
* mod.map 错乱。应拒绝编码,提示用户移除 require 引入或抽为独立工具文件。
|
|
128
|
+
*
|
|
129
|
+
* 场景 B(用户自带 `__xxx` 命名,非 lib 模块):所有 `__mod` 后缀方法对应的 mod 名
|
|
130
|
+
* 在 libs 目录均无匹配文件(如 `__getTable`、`__datetimeFormatter` 是用户私有命名,
|
|
131
|
+
* 非 lib 内模块)。此场景不会导致 lib 方法对原方法覆盖,encode 应放行编译,仅给出警告
|
|
132
|
+
* 提示(与 decode 的「未找到依赖文件」提示语义一致)。
|
|
127
133
|
*
|
|
128
134
|
* @param inPath - 源文件路径
|
|
129
135
|
* @param entry - 入口对象名
|
|
130
136
|
* @param config - 主配置
|
|
131
|
-
* @returns
|
|
137
|
+
* @returns 错误提示字符串(场景 A 时返回,阻止编码);场景 B 时返回 null 并已打印警告;
|
|
138
|
+
* 无违规返回 null
|
|
132
139
|
*/
|
|
133
140
|
function guardInlinedModMethods(inPath, entry, config) {
|
|
134
141
|
const srcAst = (0, ast_1.parseSrcAst)(inPath);
|
|
@@ -149,7 +156,38 @@ function guardInlinedModMethods(inPath, entry, config) {
|
|
|
149
156
|
return null;
|
|
150
157
|
}
|
|
151
158
|
const depNames = [...requireModPaths.keys()];
|
|
159
|
+
// 解析每个内联后缀方法名对应的 mod 名(取 split("__") 最后一段,与
|
|
160
|
+
// getUnknownDepNames / deleteModMethods 的解析逻辑保持一致)。
|
|
161
|
+
const modNames = new Set();
|
|
162
|
+
inlinedNames.forEach((name) => {
|
|
163
|
+
const split = name.split("__");
|
|
164
|
+
if (split.length >= 2) {
|
|
165
|
+
const modName = split[split.length - 1];
|
|
166
|
+
if (modName) {
|
|
167
|
+
modNames.add(modName);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
// 在 libs 目录搜索每个 mod 名是否存在独立模块文件,据此区分场景 A / B。
|
|
172
|
+
// 复用 decode 侧同一套 resolveLibDirs + scanfLibMod,保证两端判定一致。
|
|
173
|
+
const libDirs = (0, scanf_1.resolveLibDirs)(config.libs, config.baseDir, rootDir);
|
|
174
|
+
const libMods = []; // 在 libs 有匹配的 mod 名(场景 A)
|
|
175
|
+
modNames.forEach((modName) => {
|
|
176
|
+
const candidates = (0, scanf_1.scanfLibMod)(libDirs, modName);
|
|
177
|
+
if (candidates.length) {
|
|
178
|
+
libMods.push(modName);
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
// 场景 B:所有疑似后缀方法对应的 mod 名在 libs 均无匹配(非 lib 模块,多为用户自带
|
|
182
|
+
// `__xxx` 命名)。不会导致 lib 方法覆盖原方法,放行编译,仅警告提示。
|
|
183
|
+
if (!libMods.length) {
|
|
184
|
+
logger.warn(`源文件 mount 对象内存在疑似 __mod 后缀方法(${inlinedNames.join(", ")}),但对应模块在 libs 目录均无匹配,判定为非 lib 模块命名,放行编码。` +
|
|
185
|
+
`同时存在 require 依赖引入(${depNames.join(", ")})。若上述方法确为 lib 内联方法,请确认 libs 配置或手动处理。`);
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
// 场景 A:存在能在 libs 找到独立模块文件的内联后缀方法(真篡改风险),拒绝编码。
|
|
152
189
|
return (`检测到源文件 mount 对象内残留工具方法后缀(${inlinedNames.join(", ")}),` +
|
|
190
|
+
`其中 ${libMods.join(", ")} 在 libs 目录存在对应模块文件,` +
|
|
153
191
|
`同时存在 require 依赖引入(${depNames.join(", ")})。\n` +
|
|
154
192
|
`此场景不允许编码:请移除源文件中的 require 工具方法引入(${depNames
|
|
155
193
|
.map((n) => `const ${n} = require(...)`)
|
package/core/util/ast.js
CHANGED
|
@@ -557,13 +557,43 @@ function stripCommentsDeep(node) {
|
|
|
557
557
|
}
|
|
558
558
|
}
|
|
559
559
|
/**
|
|
560
|
-
*
|
|
561
|
-
*
|
|
560
|
+
* 递归统一字符串字面量的引号风格(统一为双引号)。
|
|
561
|
+
* 通过重写 extra.raw 让 generate 输出统一引号,使仅引号风格差异的代码视为相同。
|
|
562
|
+
* 仅处理 StringLiteral:方法体节点内不存在 DirectiveLiteral('use strict' 只在 Program 级)
|
|
563
|
+
* 与 JSX 属性(parse 未启用 jsx 插件),无需处理。
|
|
564
|
+
*/
|
|
565
|
+
function normalizeStringQuotesDeep(node) {
|
|
566
|
+
if (!node || typeof node !== "object") {
|
|
567
|
+
return;
|
|
568
|
+
}
|
|
569
|
+
if (Array.isArray(node)) {
|
|
570
|
+
node.forEach((child) => normalizeStringQuotesDeep(child));
|
|
571
|
+
return;
|
|
572
|
+
}
|
|
573
|
+
const n = node;
|
|
574
|
+
if (core_1.types.isStringLiteral(n)) {
|
|
575
|
+
// 统一为 JSON.stringify 生成的双引号 raw(含转义),忽略原引号风格
|
|
576
|
+
n.extra = { raw: JSON.stringify(n.value) };
|
|
577
|
+
}
|
|
578
|
+
for (const key of Object.keys(n)) {
|
|
579
|
+
if (key === "loc" || key === "start" || key === "end" || key === "range") {
|
|
580
|
+
continue;
|
|
581
|
+
}
|
|
582
|
+
const val = n[key];
|
|
583
|
+
if (val && typeof val === "object") {
|
|
584
|
+
normalizeStringQuotesDeep(val);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* 生成节点的归一化代码:去注释 + 统一字符串引号 + generate + 压缩空白/换行,
|
|
590
|
+
* 使仅注释、排版或字符串引号风格差异的代码视为相同。
|
|
562
591
|
*/
|
|
563
592
|
function normalizeNodeCode(node) {
|
|
564
593
|
// 克隆避免污染原 AST
|
|
565
594
|
const cloned = JSON.parse(JSON.stringify(node));
|
|
566
595
|
stripCommentsDeep(cloned);
|
|
596
|
+
normalizeStringQuotesDeep(cloned);
|
|
567
597
|
const { code } = (0, generator_1.default)(cloned, { compact: true });
|
|
568
598
|
// 压缩连续空白与换行,统一比较基准
|
|
569
599
|
return code.replace(/\s+/g, " ").trim();
|