FurAffinity站点Array.from转Set为空数组的问题及防护咨询
问题解答
1. 异常原因
FurAffinity的页面脚本篡改了全局的Array.from方法,或是修改了Set的迭代器实现,破坏了原生API的标准行为,导致原本能正确将Set转换为数组的Array.from失效——这类自定义实现通常只适配网站自身业务场景,忽略了标准API的通用逻辑。
2. 恢复Array.from默认行为的方法
有两种可靠方案:
- 提前保存原生引用:在用户脚本元数据中添加
@run-at document-start,让脚本在页面脚本加载前执行,此时Array.from还未被篡改,直接保存并覆盖后续被篡改的方法:
// 用户脚本开头 const nativeArrayFrom = Array.from; // 后续发现方法被篡改时,直接覆盖回去 Array.from = nativeArrayFrom;
- 从干净环境提取原生方法:创建隐藏iframe(其执行环境未被页面脚本污染),从中获取原生
Array.from:
const iframe = document.createElement('iframe'); iframe.style.display = 'none'; document.body.appendChild(iframe); const nativeArrayFrom = iframe.contentWindow.Array.from; document.body.removeChild(iframe); // 替换当前页面被篡改的方法 Array.from = nativeArrayFrom;
3. 防止网站篡改用户脚本JS方法的措施
- 提前缓存依赖的原生方法:在用户脚本最开头(配合
@run-at document-start),把需要用到的原生方法保存为局部变量,后续脚本仅使用这些缓存的引用:
const nativeArrayFrom = Array.from; const nativeTest = RegExp.prototype.test; const nativeSlice = Array.prototype.slice; // 示例使用 nativeTest.call(/abc/, 'abcdef'); const uniqueArr = nativeArrayFrom(new Set([1,2,2,3]));
- 用IIFE隔离作用域:将脚本逻辑包裹在立即执行函数中,把原生方法作为参数传入,彻底避免全局变量被篡改的影响:
(function(ArrayFrom, RegExpTest) { // 脚本内仅使用传入的原生方法 console.log(ArrayFrom(new Set([1,2,2,3]))); console.log(RegExpTest.call(/test/, 'test string')); })(Array.from, RegExp.prototype.test);
- 减少对全局原型方法的依赖:优先使用原生语法糖替代可能被篡改的API,比如用扩展运算符
[...new Set([1,2,2,3])]替代Array.from;必要时自己实现轻量逻辑,降低对全局API的依赖。
内容的提问来源于stack exchange,提问作者AAsomb113
相关产品推荐
相关产品推荐

